/** * Sort comparator for ch_ring_entry structs on pos, ip and instance. */ static int entrycmp_carbon(const void *l, const void *r) { ch_ring_entry *ch_l = (ch_ring_entry *)l; ch_ring_entry *ch_r = (ch_ring_entry *)r; if (ch_l->pos != ch_r->pos) return ch_l->pos - ch_r->pos; #ifndef CH_CMP_V40_BEHAVIOUR { int d = strcmp(server_ip(ch_l->server), server_ip(ch_r->server)); char *i_l, *i_r; if (d != 0) return d; i_l = server_instance(ch_l->server); i_r = server_instance(ch_r->server); if (i_l == NULL && i_r == NULL) return 0; if (i_l == NULL) return 1; if (i_r == NULL) return -1; return strcmp(i_l, i_r); } #endif return 0; }
void dsme_dbus_bind_methods(bool* bound_already, const dsme_dbus_binding_t* bindings, const char* service, const char* interface) { if (bound_already && !*bound_already) { const dsme_dbus_binding_t* binding = bindings; while (binding && binding->method) { if (!server_bind(server_instance(), binding->method, service, interface, binding->name, 0)) { dsme_log(LOG_ERR, "D-Bus binding for '%s' failed", binding->name); // TODO: roll back the ones that succeeded and break? } ++binding; } *bound_already = true; } }
void ch_printhashring(ch_ring *ring, FILE *f) { ch_ring_entry *w; char column = 0; char srvbuf[21]; for (w = ring->entries; w != NULL; w = w->next) { snprintf(srvbuf, sizeof(srvbuf), "%s:%d%s%s", server_ip(w->server), server_port(w->server), server_instance(w->server) ? "=" : "", server_instance(w->server) ? server_instance(w->server) : ""); fprintf(f, "%5d@%-20s", w->pos, srvbuf); if (column < 2) { fprintf(f, " "); column++; } else { fprintf(f, "\n"); column = 0; } } }
int main(int, char*[]) { dummy_async_handler async_handler; #define ASYNC_SERVER_TEST_CONFIG \ options.address("127.0.0.1").port("8007").reuse_address(true) #define ASYNC_SERVER_SLEEP_TIME std::chrono::milliseconds(100) // stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop without running"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); server_instance.stop(); } // run-stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); server_instance.stop(); running_thread.join(); } // run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); } // run-stop-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_stopping_thread.join(); second_running_thread.join(); } // run-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_running_thread.join(); } // run-stop-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); second_stopping_thread.join(); running_thread.join(); } #undef ASYNC_SERVER_TEST_CONFIG return 0; }
int main(int argc, char * argv[]) { dummy_async_handler async_handler; #define ASYNC_SERVER_TEST_CONFIG \ options.address("127.0.0.1") \ .port("8007") \ .reuse_address(true) #define ASYNC_SERVER_SLEEP_TIME \ boost::posix_time::milliseconds(100) // stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop without running"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); server_instance.stop(); } // run-stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); server_instance.stop(); running_thread.join(); } // run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); } // run-stop-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_stopping_thread.join(); second_running_thread.join(); } // run-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_running_thread.join(); } // run-stop-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); second_stopping_thread.join(); running_thread.join(); } #undef ASYNC_SERVER_TEST_CONFIG return 0; }
/** * Computes the hash positions for the server name given. This is based * on the hashpos function. The server name usually is the IPv4 * address. The port component is just stored and not used in the * carbon hash calculation in case of carbon_ch. The instance component * is used in the hash calculation of carbon_ch, it is ignored for * fnv1a_ch. Returns an updated ring. */ ch_ring * ch_addnode(ch_ring *ring, server *s) { int i; char buf[256]; ch_ring_entry *entries; char *instance = server_instance(s); int (*cmp)(const void *, const void *) = NULL; if (ring == NULL) return NULL; entries = (ch_ring_entry *)malloc(sizeof(ch_ring_entry) * ring->hash_replicas); if (entries == NULL) return NULL; switch (ring->type) { case CARBON: for (i = 0; i < ring->hash_replicas; i++) { /* this format is actually Python's tuple format that is * used in serialised form as input for the hash */ snprintf(buf, sizeof(buf), "('%s', %s%s%s):%d", server_ip(s), instance == NULL ? "" : "'", instance == NULL ? "None" : instance, instance == NULL ? "" : "'", i); /* carbon upstream committed: * https://github.com/graphite-project/carbon/commit/024f9e67ca47619438951c59154c0dec0b0518c7 * this makes sure no collissions exist on pos, however, * at the expense of being agnostic to the input order, * therefore that change isn't implemented here, see * https://github.com/grobian/carbon-c-relay/issues/84 */ entries[i].pos = carbon_hashpos(buf, buf + strlen(buf)); entries[i].server = s; entries[i].next = NULL; entries[i].malloced = 0; } cmp = *entrycmp_carbon; break; case FNV1a: for (i = 0; i < ring->hash_replicas; i++) { /* take all server info into account, such that * different port numbers for the same hosts will work * (unlike CARBON), unless we got a full overrride */ if (instance == NULL) { snprintf(buf, sizeof(buf), "%d-%s:%u", i, server_ip(s), server_port(s)); } else { snprintf(buf, sizeof(buf), "%d-%s", i, instance); } entries[i].pos = fnv1a_hash16(buf, buf + strlen(buf)); entries[i].server = s; entries[i].next = NULL; entries[i].malloced = 0; } cmp = *entrycmp_fnv1a; break; } /* sort to allow merge joins later down the road */ qsort(entries, ring->hash_replicas, sizeof(ch_ring_entry), cmp); entries[0].malloced = 1; if (ring->entries == NULL) { for (i = 1; i < ring->hash_replicas; i++) entries[i - 1].next = &entries[i]; ring->entries = entries; } else { /* merge-join the two rings */ ch_ring_entry *w, *last; i = 0; last = NULL; assert(ring->hash_replicas > 0); for (w = ring->entries; w != NULL && i < ring->hash_replicas; ) { if (cmp(&w->pos, &entries[i].pos) <= 0) { last = w; w = w->next; } else { entries[i].next = w; if (last == NULL) { ring->entries = &entries[i]; } else { last->next = &entries[i]; } last = &entries[i]; i++; } } if (w != NULL) { last->next = w; } else { last->next = &entries[i]; for (i = i + 1; i < ring->hash_replicas; i++) entries[i - 1].next = &entries[i]; } } return ring; }