fsmonitor--daemon: define token-ids
Teach fsmonitor--daemon to create token-ids and define the overall token naming scheme. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
0ae7a1d9ab
commit
aeef767a41
@ -106,6 +106,120 @@ static int do_as_client__status(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Requests to and from a FSMonitor Protocol V2 provider use an opaque
|
||||
* "token" as a virtual timestamp. Clients can request a summary of all
|
||||
* created/deleted/modified files relative to a token. In the response,
|
||||
* clients receive a new token for the next (relative) request.
|
||||
*
|
||||
*
|
||||
* Token Format
|
||||
* ============
|
||||
*
|
||||
* The contents of the token are private and provider-specific.
|
||||
*
|
||||
* For the built-in fsmonitor--daemon, we define a token as follows:
|
||||
*
|
||||
* "builtin" ":" <token_id> ":" <sequence_nr>
|
||||
*
|
||||
* The "builtin" prefix is used as a namespace to avoid conflicts
|
||||
* with other providers (such as Watchman).
|
||||
*
|
||||
* The <token_id> is an arbitrary OPAQUE string, such as a GUID,
|
||||
* UUID, or {timestamp,pid}. It is used to group all filesystem
|
||||
* events that happened while the daemon was monitoring (and in-sync
|
||||
* with the filesystem).
|
||||
*
|
||||
* Unlike FSMonitor Protocol V1, it is not defined as a timestamp
|
||||
* and does not define less-than/greater-than relationships.
|
||||
* (There are too many race conditions to rely on file system
|
||||
* event timestamps.)
|
||||
*
|
||||
* The <sequence_nr> is a simple integer incremented whenever the
|
||||
* daemon needs to make its state public. For example, if 1000 file
|
||||
* system events come in, but no clients have requested the data,
|
||||
* the daemon can continue to accumulate file changes in the same
|
||||
* bin and does not need to advance the sequence number. However,
|
||||
* as soon as a client does arrive, the daemon needs to start a new
|
||||
* bin and increment the sequence number.
|
||||
*
|
||||
* The sequence number serves as the boundary between 2 sets
|
||||
* of bins -- the older ones that the client has already seen
|
||||
* and the newer ones that it hasn't.
|
||||
*
|
||||
* When a new <token_id> is created, the <sequence_nr> is reset to
|
||||
* zero.
|
||||
*
|
||||
*
|
||||
* About Token Ids
|
||||
* ===============
|
||||
*
|
||||
* A new token_id is created:
|
||||
*
|
||||
* [1] each time the daemon is started.
|
||||
*
|
||||
* [2] any time that the daemon must re-sync with the filesystem
|
||||
* (such as when the kernel drops or we miss events on a very
|
||||
* active volume).
|
||||
*
|
||||
* [3] in response to a client "flush" command (for dropped event
|
||||
* testing).
|
||||
*
|
||||
* When a new token_id is created, the daemon is free to discard all
|
||||
* cached filesystem events associated with any previous token_ids.
|
||||
* Events associated with a non-current token_id will never be sent
|
||||
* to a client. A token_id change implicitly means that the daemon
|
||||
* has gap in its event history.
|
||||
*
|
||||
* Therefore, clients that present a token with a stale (non-current)
|
||||
* token_id will always be given a trivial response.
|
||||
*/
|
||||
struct fsmonitor_token_data {
|
||||
struct strbuf token_id;
|
||||
struct fsmonitor_batch *batch_head;
|
||||
struct fsmonitor_batch *batch_tail;
|
||||
uint64_t client_ref_count;
|
||||
};
|
||||
|
||||
static struct fsmonitor_token_data *fsmonitor_new_token_data(void)
|
||||
{
|
||||
static int test_env_value = -1;
|
||||
static uint64_t flush_count = 0;
|
||||
struct fsmonitor_token_data *token;
|
||||
|
||||
CALLOC_ARRAY(token, 1);
|
||||
|
||||
strbuf_init(&token->token_id, 0);
|
||||
token->batch_head = NULL;
|
||||
token->batch_tail = NULL;
|
||||
token->client_ref_count = 0;
|
||||
|
||||
if (test_env_value < 0)
|
||||
test_env_value = git_env_bool("GIT_TEST_FSMONITOR_TOKEN", 0);
|
||||
|
||||
if (!test_env_value) {
|
||||
struct timeval tv;
|
||||
struct tm tm;
|
||||
time_t secs;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
secs = tv.tv_sec;
|
||||
gmtime_r(&secs, &tm);
|
||||
|
||||
strbuf_addf(&token->token_id,
|
||||
"%"PRIu64".%d.%4d%02d%02dT%02d%02d%02d.%06ldZ",
|
||||
flush_count++,
|
||||
getpid(),
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||
(long)tv.tv_usec);
|
||||
} else {
|
||||
strbuf_addf(&token->token_id, "test_%08x", test_env_value++);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
static ipc_server_application_cb handle_client;
|
||||
|
||||
static int handle_client(void *data,
|
||||
@ -298,7 +412,7 @@ static int fsmonitor_run_daemon(void)
|
||||
|
||||
pthread_mutex_init(&state.main_lock, NULL);
|
||||
state.error_code = 0;
|
||||
state.current_token_data = NULL;
|
||||
state.current_token_data = fsmonitor_new_token_data();
|
||||
|
||||
/* Prepare to (recursively) watch the <worktree-root> directory. */
|
||||
strbuf_init(&state.path_worktree_watch, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user