Module Bogue.File.Monitor

module Monitor: sig .. end

Monitoring changes in a directory.

This module provides functions for watching for changes in a directory (or a single file), and executing arbitrary actions when a change is detected.

All functions are non-blocking and return very fast, even if the path is remote or the directory is huge. To achieve this, monitoring is done in a separate thread and one has to accept a delay before actual changes to the file-system are reported.

We provide two implementations, one is based on the external fswatch program, and the other is based on the built-in Ocaml function Unix.stat. The fswatch implementation is automatically chosen by default if the fswatch executable is detected. Otherwise, the Unix.stat fallback is used (which is maybe more memory and cpu intensive).


type t 
val path : t -> string

Return the monitored path.

val start : ?delay:float ->
?action:(t -> unit) -> string -> t

start path starts monitoring the directory or file path and immediately returns. It is not an error if path does not exist or is deleted, see below. Once monitoring has started, check the File.Monitor.modified function below to obtain the actual changes.

delay : the time interval (in seconds) between polls. The default delay is 1 second. It may be internally increased if the polls take too much time.
action : executed for each modification. Note that false positive may happen; hence the action should be fast and non blocking (typically just sending an event).
val delay : t -> float

Return the delay (in seconds) between two polls.

val stop : t -> unit

Kill the monitoring process.

val ls : t -> string list

ls m returns the list of files watched by the monitor  m  when the last *modified function was called. Thus, it may be different from the actual current content. If  m  monitors a directory, ls m is the content of the directory (without "." and ".."), otherwise ls m is ["."] if the file exists, or [] if not. This function takes advantage of the monitoring data to return faster (in general) than rescanning the directory with Sys.readdir.

val size : t -> int option

If t monitors a directory, then size t is the number of elements of this directory, before recent modifications. Otherwise, size t returns None. Calling size t is equivalent to but faster than List.length (ls t).

val modified : t -> string list * string list * string list

Return three lists of file (or directory) names that have been modified since last call of this function or of was_modified:

list of deleted elements, list of added elements, list of modified elements

File names do not include the directory path. These lists can be equal to the singleton ["."] in some special cases:

  1. if the path now exists but did not exist in the previous call to *modified, then the added list is ["."] and the others are empty (even if some contents of path were modified in the meantime: remember that we only compare to the previous call to *modified.)
  2. if the path existed in the previous call to *modified but not anymore, then the deleted list is ["."] and the others are empty.
  3. if the path existed in the previous call to *modified, then has disappeared and then reappeared again, the modified function will return [], ["."], [] instead of the explicit difference, telling you that it is safer to read the contents again (using ls for instance).
val was_modified : t -> bool

Simply returns true if files were modified since the last call of this function or of modified. The list of modified files cannot be retrieved. This is (semantically) equivalent to checking if the lists returned by modified are empty, but possibly faster.