void register_existing_partners (void) { GList *iter = NULL; char *value = NULL; char *path = NULL; /* get all paths under the APTERYX_SYNC_PATH node * note: need to add a "/" on the end for search to work */ GList *existing_partners = apteryx_search (APTERYX_SYNC_PATH "/"); /* for each path in the search result, get the value and create a new syncer */ iter = existing_partners; while (iter != NULL) { DEBUG ("Adding existing partner %s\n", (char *)iter->data); /* the path is a char* in the iter->data. need to add "/*" to the end */ if (asprintf (&path, "%s/*", (char *)iter->data) <= 0) { /* shouldn't fail, but if it does we can't do any more with it */ continue; } value = apteryx_get (path); new_syncer (path, value); free (value); free (path); /* finished with this entry. move along, nothing to see here. */ iter = iter->next; } /* finally, clean up the list */ g_list_free_full (existing_partners, free); existing_partners = NULL; }
bool sync_recursive (sync_partner *sp, const char *path) { uint64_t ts = apteryx_timestamp (path); if (ts < sp->last_sync_local) { if (ts == 0) { /* Prune anything that is deleted */ apteryx_prune_sp (sp, path); } /* Skip anything that hasn't changed since last sync */ return true; } /* make sure the path doesn't end in '/' for the get */ char *get_path = strdup (path); if (get_path[strlen (get_path) - 1] == '/') { get_path[strlen (get_path) - 1] = '\0'; } /* now make sure the path ends in '/' for the search */ char *search_path = NULL; if (path[strlen (path) - 1] != '/') { if (asprintf (&search_path, "%s/", path) == -1) { ERROR ("SYNC couldn't allocate search path!\n"); search_path = NULL; free (get_path); return false; } } else { search_path = strdup (path); } /* Update this node */ char *value = apteryx_get (get_path); if (value) { /* only sync non-null values or you'll inadvertently prune */ apteryx_set_sp (sp, get_path, value); free (value); } free (get_path); /* Update all children */ GList *sync_paths = apteryx_search (search_path); free (search_path); for (GList *iter = sync_paths; iter; iter = iter->next) { sync_recursive (sp, iter->data); } g_list_free_full (sync_paths, free); // TODO: Update remote children that weren't already covered above // Specifically, look for local deletes that haven't propagated return true; }
/* Application entry point */ int main (int argc, char **argv) { const char *filter = NULL; APTERYX_MODE mode = -1; char *path = NULL; char *param = NULL; GList * _iter; int c; uint64_t value; /* Parse options */ while ((c = getopt (argc, argv, "hdsgftwpxlu::")) != -1) { switch (c) { case 'd': apteryx_debug = true; break; case 's': mode = MODE_SET; break; case 'g': mode = MODE_GET; break; case 'f': mode = MODE_FIND; break; case 't': mode = MODE_TRAVERSE; break; case 'w': mode = MODE_WATCH; break; case 'p': mode = MODE_PROVIDE; break; case 'x': mode = MODE_PROXY; break; case 'l': mode = MODE_TIMESTAMP; break; case 'u': mode = MODE_TEST; if (optarg && optarg[0] == '=') memmove(optarg, optarg+1, strlen(optarg)); filter = optarg; break; case '?': case 'h': default: usage (); return 0; } } for (c = optind; c < argc; c++) { if (path == NULL) path = argv[c]; else if (param == NULL) param = argv[c]; else { usage (); return 0; } } /* Handle SIGTERM/SIGINT/SIGPIPE gracefully */ if (mode != MODE_TEST) { signal (SIGTERM, (__sighandler_t) termination_handler); signal (SIGINT, (__sighandler_t) termination_handler); } switch (mode) { case MODE_GET: if (!path || param) { usage (); return 0; } apteryx_init (apteryx_debug); if ((param = apteryx_get (path))) { printf ("%s\n", param); free (param); } else printf ("Not found\n"); apteryx_shutdown (); break; case MODE_SET: if (!path) { usage (); return 0; } apteryx_init (apteryx_debug); if (!apteryx_set (path, param)) printf ("Failed\n"); apteryx_shutdown (); break; case MODE_FIND: if (!path || param) { usage (); return 0; } apteryx_init (apteryx_debug); GList *paths = apteryx_search (path); for (_iter = paths; _iter; _iter = _iter->next) printf (" %s\n", (char *) _iter->data); g_list_free_full (paths, free); apteryx_shutdown (); break; case MODE_TRAVERSE: if (param) { usage (); return 0; } if (!path) { path = ""; } apteryx_init (apteryx_debug); apteryx_dump (path, stdout); apteryx_shutdown (); break; case MODE_WATCH: if (param) { usage (); return 0; } if (!path) { path = "/"; } apteryx_init (apteryx_debug); apteryx_watch (path, watch_callback); while (running) pause (); apteryx_unwatch (path, watch_callback); apteryx_shutdown (); break; case MODE_PROVIDE: if (!path || !param) { usage (); return 0; } apteryx_init (apteryx_debug); provide_value = param; apteryx_provide (path, provide_callback); while (running) pause (); apteryx_unprovide (path, provide_callback); apteryx_shutdown (); break; case MODE_PROXY: if (!path || !param) { usage (); return 0; } apteryx_init (apteryx_debug); apteryx_proxy (path, param); apteryx_shutdown (); break; case MODE_TIMESTAMP: if (param) { usage (); return 0; } if (!path) { path = ""; } apteryx_init (apteryx_debug); value = apteryx_timestamp (path); printf ("%"PRIu64"\n", value); apteryx_shutdown (); break; case MODE_TEST: if (path || param) { usage (); return 0; } apteryx_init (apteryx_debug); run_unit_tests (filter); usleep (100000); apteryx_shutdown (); break; default: usage (); return 0; } return 0; }