Module zotonic_filewatcher_monitor

Erlang file monitoring service.

Copyright © 2006-2009 Richard Carlsson

Behaviours: gen_server.

Authors: Richard Carlsson (carlsson.richard@gmail.com).

Description

Erlang file monitoring service

The behaviour of this service is inspired by the open source FAM daemon (http://oss.sgi.com/projects/fam/). It allows file system paths to be monitored, so that a message will be sent to the client process whenever a status change is detected. Currently, the only supported method of detection is by regular polling by the server. While it is not optimal, polling has less overhead than might be expected, and is portable across platforms. The polling interval can be adjusted; by default the server polls all monitored paths every 5 seconds. Recursive (automatic) monitoring is supported. The server keeps track of its client processes, and removes all their monitors if they should die.

Event messages

When a new monitor is set up, or a change is detected, an event message is sent to the client. These have the following general form:
{file_monitor, Ref::monitor(), Event}
where Ref is the monitor reference returned when the monitor was set up, and Event is one of the following:

where Path is the watched path (as a binary), Type is the type of monitoring being performed (either file or directory), Info is a file_info record as defined in kernel/include/file.hrl, and Entries is a list of tuples {added, binary()} and {deleted, binary()} describing changes to the directory entries if Type is directory, otherwise this is always the empty list. For a found event, all entries are {added, Name}.

A found event is sent when a monitor is initially set up, if the path can be read. After that, whenever a change in status is detected, a changed event is sent. If the file does not exist or could for some other reason not be accessed, an error event is sent (both initially and for subsequent changes). In other words, the first event for a path is always either found or error, and later events are either changed or error.

Detection of file type changes

If the object found at a path changes type in the interval between two polls, for example if a directory is replaced by a file with the same name, or vice versa, the file monitor server will detect this and dispatch an enoent error event before the new status event. A client can thus rely on always seeing the old file disappear before any change that reports a different file type.

Monitoring types

There are two ways in which a path can be monitored: as a file, meaning that we are interested only in the object found at that path, or as a directory, meaning that we expect the path to point to a directory, and we are also interested in the list of entries of that directory.

If a path is monitored as a directory, and the object at the path exists but is not a directory, an enotdir error event will be generated. An existing directory can however both be monitored as a directory and as a file - the difference is that in the latter case, the reported list of entries will always be empty.

Automatic (recursive) monitoring

Automatic monitoring (automonitoring for short) can be used to watch a single file of any type, or a whole directory tree. The monitoring type (file or directory) used for any path is based on the actual type of object found at the path (directory if the object is a readable directory, and file otherwise). If the object is replaced by another of different type, the monitoring type will change automatically.

When a directory becomes automonitored, all of its entries will also be automatically monitored, recursively. As entries are created or deleted in an automonitored directory, they will be dynamically added or removed, respectively, from being monitored. The root path used to create the automonitor will however always remain monitored (even if the object temporarily or permanently disappears) until the server is told to delete the monitor.

The event messages sent to the client are the same as if manual monitoring was done. A newly discovered path will be reported by a found (or possibly, by an error event), and subsequent changes on that path are reported by changed and error events. If the monitoring type is changed, a new found event is sent, and so on.

Data Types

filename()

filename() = binary() | atom() | [char() | filename()]

This is an "extended IO-list", that allows atoms as well as binaries to occur either on their own or embedded in a list or deep list. The intent of this is to accept any file name that can be used by the standard library module file, as well as any normal IO-list, and any list that is formed by combining such fragments.

monitor()

monitor() = reference()

A monitor reference.

options()

options() = [term()]

A list of options.

server_ref()

server_ref() = pid() | atom() | {Node::atom(), atom()} | {global, atom()}

A reference to a running server. See //stdlib/gen_server:call/3 for more information.

Function Index

automonitor/1Equivalent to automonitor(Path, []).
automonitor/2Equivalent to automonitor(file_monitor, Path, Opts).
automonitor/3Automonitors the specified path.
demonitor/1Equivalent to demonitor(file_monitor, Ref).
demonitor/2Deletes the specified monitor.
demonitor_dir/2Equivalent to demonitor_dir(file_monitor, Path, Ref).
demonitor_dir/3Removes the directory path from the specified monitor.
demonitor_file/2Equivalent to demonitor_file(file_monitor, Path, Ref).
demonitor_file/3Removes the file path from the specified monitor.
get_interval/0Equivalent to get_interval(file_monitor).
get_interval/1Returns the current polling interval.
monitor_dir/1Equivalent to monitor_dir(Path, []).
monitor_dir/2Equivalent to monitor_dir(file_monitor, Path, Opts).
monitor_dir/3Monitors the specified directory path.
monitor_file/1Equivalent to monitor_file(Path, []).
monitor_file/2Equivalent to monitor_file(file_monitor, Path, Opts).
monitor_file/3Monitors the specified file path.
normalize_path/1Flattens the given path to a single binary.
set_interval/1Equivalent to set_interval(file_monitor, Time).
set_interval/2Sets the polling interval.
start/0Equivalent to start([]).
start/1Equivalent to start({local, file_monitor}, Options).
start/2Starts the server and registers it using the specified name.
start_link/0Equivalent to start_link([]).
start_link/1Equivalent to start_link({local, file_monitor}, Options).
start_link/2Starts the server, links it to the current process, and registers it using the specified name.
stop/0Equivalent to stop(file_monitor).
stop/1Stops the specified server.

Function Details

automonitor/1

automonitor(Path::filename()) -> {ok, monitor(), binary()}

Equivalent to automonitor(Path, []).

automonitor/2

automonitor(Path::filename(), Opts::options()) -> {ok, monitor(), binary()}

Equivalent to automonitor(file_monitor, Path, Opts).

automonitor/3

automonitor(Server::server_ref(), Path::filename(), Opts::options()) -> {ok, monitor(), binary()}

Automonitors the specified path. Returns the monitor reference as well as the monitored path as a binary.

Options: none at present.

demonitor/1

demonitor(Ref::monitor()) -> ok | {error, not_owner}

Equivalent to demonitor(file_monitor, Ref).

demonitor/2

demonitor(Server::server_ref(), Ref::monitor()) -> ok | {error, not_owner}

Deletes the specified monitor. This can only be done by the process that created the monitor.

demonitor_dir/2

demonitor_dir(Path::filename(), Ref::monitor()) -> ok | {error, not_owner}

Equivalent to demonitor_dir(file_monitor, Path, Ref).

demonitor_dir/3

demonitor_dir(Server::server_ref(), Path::filename(), Ref::monitor()) -> ok | {error, not_owner}

Removes the directory path from the specified monitor. This can only be done by the process that created the monitor.

demonitor_file/2

demonitor_file(Path::filename(), Ref::monitor()) -> ok | {error, not_owner}

Equivalent to demonitor_file(file_monitor, Path, Ref).

demonitor_file/3

demonitor_file(Server::server_ref(), Path::filename(), Ref::monitor()) -> ok | {error, not_owner}

Removes the file path from the specified monitor. This can only be done by the process that created the monitor.

get_interval/0

get_interval() -> integer()

Equivalent to get_interval(file_monitor).

get_interval/1

get_interval(Server::server_ref()) -> integer()

Returns the current polling interval.

monitor_dir/1

monitor_dir(Path::filename()) -> {ok, monitor(), binary()} | {error, not_owner | automonitor}

Equivalent to monitor_dir(Path, []).

monitor_dir/2

monitor_dir(Path::filename(), Opts::options()) -> {ok, monitor(), binary()} | {error, not_owner | automonitor}

Equivalent to monitor_dir(file_monitor, Path, Opts).

monitor_dir/3

monitor_dir(Server::server_ref(), Path::filename(), Opts::options()) -> {ok, monitor(), binary()} | {error, not_owner | automonitor}

Monitors the specified directory path. Returns the monitor reference as well as the monitored path as a binary.

Options: see monitor_file/3.

monitor_file/1

monitor_file(Path::filename()) -> {ok, monitor(), binary()} | {error, not_owner | automonitor}

Equivalent to monitor_file(Path, []).

monitor_file/2

monitor_file(Path::filename(), Opts::options()) -> {ok, monitor(), binary()} | {error, not_owner | automonitor}

Equivalent to monitor_file(file_monitor, Path, Opts).

monitor_file/3

monitor_file(Server::server_ref(), Path::filename(), Opts::options()) -> {ok, monitor(), binary()} | {error, not_owner | automonitor}

Monitors the specified file path. Returns the monitor reference as well as the monitored path as a binary.

Options:

normalize_path/1

normalize_path(Path::filename()) -> binary()

Flattens the given path to a single binary.

set_interval/1

set_interval(Time::integer()) -> ok

Equivalent to set_interval(file_monitor, Time).

set_interval/2

set_interval(Server::server_ref(), Time::integer()) -> ok

Sets the polling interval. Units are in milliseconds.

start/0

start() -> {ok, ServerPid::pid()} | ignore | {error, any()}

Equivalent to start([]).

start/1

start(Options::options()) -> {ok, ServerPid::pid()} | ignore | {error, any()}

Equivalent to start({local, file_monitor}, Options).

start/2

start(Name::{local, atom()} | {global, atom()} | undefined, Options::options()) -> {ok, ServerPid::pid()} | ignore | {error, any()}

Starts the server and registers it using the specified name. If the name is undefined, the server will not be registered. See //stdlib/gen_server:start_link/4 for details about the return value.

Options:

start_link/0

start_link() -> {ok, ServerPid::pid()} | ignore | {error, any()}

Equivalent to start_link([]).

start_link/1

start_link(Options::options()) -> {ok, ServerPid::pid()} | ignore | {error, any()}

Equivalent to start_link({local, file_monitor}, Options).

start_link/2

start_link(Name::{local, atom()} | {global, atom()} | undefined, Options::options()) -> {ok, ServerPid::pid()} | ignore | {error, any()}

Starts the server, links it to the current process, and registers it using the specified name. If the name is undefined, the server will not be registered. See //stdlib/gen_server:start_link/4 for details about the return value.

Options: see start/2.

stop/0

stop() -> ok

Equivalent to stop(file_monitor).

stop/1

stop(Server::server_ref()) -> ok

Stops the specified server.


Generated by EDoc