MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / cbm_watcher_watch

Function cbm_watcher_watch

src/watcher/watcher.c:931–998  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

929/* ── Watch list management ──────────────────────────────────────── */
930
931bool cbm_watcher_watch(cbm_watcher_t *w, const char *project_name, const char *root_path) {
932 if (!w || !project_name || !project_name[0] || !root_path || !root_path[0] ||
933 atomic_load_explicit(&w->stopped, memory_order_acquire)) {
934 return false;
935 }
936
937 project_state_t *s = state_new(project_name, root_path);
938 if (!s) {
939 cbm_log_warn("watcher.watch.oom", "project", project_name, "path", root_path);
940 return false;
941 }
942
943 cbm_mutex_lock(&w->projects_lock);
944 if (atomic_load_explicit(&w->stopped, memory_order_acquire)) {
945 cbm_mutex_unlock(&w->projects_lock);
946 state_free(s);
947 return false;
948 }
949 project_state_t *old = cbm_ht_get(w->projects, project_name);
950 if (old && strcmp(old->root_path, s->root_path) == 0) {
951 /* Multiple daemon sessions may subscribe to the same canonical
952 * project/root. Re-registering that identical watch must not discard
953 * its git baseline, pending dirty signature, or immediate-touch state. */
954 cbm_mutex_unlock(&w->projects_lock);
955 state_free(s);
956 return true;
957 }
958 if (old) {
959 /* A poll snapshot may still be using the old state, including while
960 * its index callback calls back into this function. Queue it before
961 * removing the table entry; on OOM, preserve the existing watch. */
962 if (!defer_state_free(w, old)) {
963 cbm_mutex_unlock(&w->projects_lock);
964 state_free(s);
965 return false;
966 }
967 cbm_ht_delete(w->projects, project_name);
968 }
969 cbm_ht_set(w->projects, s->project_name, s);
970 bool registered = cbm_ht_get(w->projects, project_name) == s;
971 if (!registered && old) {
972 /* Restore the original table entry and remove the deferred-free slot.
973 * The lock keeps this rollback invisible to poll/watch callers. */
974 cbm_ht_set(w->projects, old->project_name, old);
975 if (cbm_ht_get(w->projects, project_name) == old) {
976 w->pending_free[--w->pending_free_count] = NULL;
977 } else {
978 atomic_store_explicit(&old->registered, false, memory_order_release);
979 if (old->active_git) {
980 (void)cbm_subprocess_request_cancel(old->active_git);
981 }
982 }
983 }
984 if (registered && old) {
985 atomic_store_explicit(&old->registered, false, memory_order_release);
986 if (old->active_git) {
987 (void)cbm_subprocess_request_cancel(old->active_git);
988 }

Callers 6

test_watcher.cFile · 0.85
test_httpd.cFile · 0.85

Calls 9

state_newFunction · 0.85
cbm_mutex_lockFunction · 0.85
cbm_mutex_unlockFunction · 0.85
state_freeFunction · 0.85
cbm_ht_getFunction · 0.85
defer_state_freeFunction · 0.85
cbm_ht_deleteFunction · 0.85
cbm_ht_setFunction · 0.85

Tested by 1