static void deregister_the_client (client_t *self) { // If the client never sent CONNECTION_OPEN then self->address was // never set, so avoid trying to dereference it. Nothing needs to // be cleaned up. if (self->address) { if (*self->address) zsys_info ("client %u address='%s' - de-registering", self->unique_id, self->address); // Cancel all stream subscriptions stream_t *stream = (stream_t *) zlistx_detach (self->readers, NULL); while (stream) { zsock_send (stream->actor, "sp", "CANCEL", self); stream = (stream_t *) zlistx_detach (self->readers, NULL); } // Cancel all service offerings service_t *service = (service_t *) zhashx_first (self->server->services); while (service) { offer_t *offer = (offer_t *) zlistx_first (service->offers); while (offer) { if (offer->client == self) zlistx_delete (service->offers, zlistx_cursor (service->offers)); offer = (offer_t *) zlistx_next (service->offers); } service = (service_t *) zhashx_next (self->server->services); } if (*self->address) zhashx_delete (self->server->clients, self->address); } mlm_proto_set_status_code (self->message, MLM_PROTO_SUCCESS); }
static void deregister_the_client (client_t *self) { if (*self->address) zsys_info ("client address='%s' - de-registering", self->address); // Cancel all stream subscriptions stream_t *stream = (stream_t *) zlistx_detach (self->readers, NULL); while (stream) { zsock_send (stream->actor, "sp", "CANCEL", self); stream = (stream_t *) zlistx_detach (self->readers, NULL); } // Cancel all service offerings service_t *service = (service_t *) zhashx_first (self->server->services); while (service) { offer_t *offer = (offer_t *) zlistx_first (service->offers); while (offer) { if (offer->client == self) zlistx_delete (service->offers, zlistx_cursor (service->offers)); offer = (offer_t *) zlistx_next (service->offers); } service = (service_t *) zhashx_next (self->server->services); } if (*self->address) zhashx_delete (self->server->clients, self->address); mlm_proto_set_status_code (self->message, MLM_PROTO_SUCCESS); }
void zgtask_tree_destroy (zgtask_tree_t **self_p) { assert (self_p); if (*self_p) { zgtask_tree_t *self = *self_p; // Free class properties free (self->name); zgtask_tree_destroy (&self->child); zgtask_tree_destroy (&self->brother); // Cleaning net zgtask_net_t *net = zgtask_tree_get_net (self); if (net) { zgtask_net_destroy (&net); zhashx_delete (self->data, "net"); } // Cleaning task zgtask_task_t *task = zgtask_tree_get_task (self); if (task) { zgtask_task_destroy (&task); zhashx_delete (self->data, "task"); } // Cleaning packet zgtask_packet_t *packet = zgtask_tree_get_packet (self); if (packet) { zgtask_packet_destroy (&packet); zhashx_delete (self->data, "packet"); } // Destroying data table zhashx_destroy (&self->data); // Free object itself free (self); *self_p = NULL; } }
static void client_terminate (client_t *self) { zlistx_destroy (&self->readers); // The client can be terminated in two ways. // 1. Some event (connection_close, expired, exception) // de-register the client. When this happens, deregister_the_client () // will be called cancelling all of its streams, services and // free'ing some internal properties by the zhashx destructor set in // the server application-level context (server_t). After all stream // engine's references are dropped, client_terminate () is called. This // routine must free its properties allocated by client_initialize (). // This is the regular case. // 2. The server ends for some reason (interrupted, most likely). // This causes s_server_destroy () to be called and, among other things, // destroy the general context for the client (s_client_t) by means // of the zhash destructor and then calls server_destroy (), which // will destroy all of the client application-level context (client_t) // by means of the zhashx destructor. // // Case #1 is handled by just setting the application-level context // (server_t) zhashx destructor and the client address will be free correctly // and we just need to be sure not to double free it again here. // Case #2 needs to handled a bit different as the server application-level context // (server_t) client zhashx destructor will not be called until after the // general context for the client is already destroyed. So, we need to free // its address here, as well. We do this by deleting ourselves from the // hash and letting the destructor takes care of the cleaning. // // In all cases, we must make sure that the string is not NULL (it was free'd // before) or it is empty (client will not be in hashx, but the address // would be allocated either way. if (self->address) { if (*self->address) zhashx_delete (self->server->clients, self->address); else zstr_free (&self->address); } }
JNIEXPORT void JNICALL Java_org_zeromq_czmq_Zhashx__1_1delete (JNIEnv *env, jclass c, jlong self, jlong key) { zhashx_delete ((zhashx_t *) (intptr_t) self, (const void *) (intptr_t) key); }
static void deregister_the_client (client_t *self) { zhashx_delete (self->server->clients, zuuid_str (self->id)); }
void zhashx_test (int verbose) { printf (" * zhashx: "); // @selftest zhashx_t *hash = zhashx_new (); assert (hash); assert (zhashx_size (hash) == 0); assert (zhashx_first (hash) == NULL); assert (zhashx_cursor (hash) == NULL); // Insert some items int rc; rc = zhashx_insert (hash, "DEADBEEF", "dead beef"); char *item = (char *) zhashx_first (hash); assert (streq ((char *) zhashx_cursor (hash), "DEADBEEF")); assert (streq (item, "dead beef")); assert (rc == 0); rc = zhashx_insert (hash, "ABADCAFE", "a bad cafe"); assert (rc == 0); rc = zhashx_insert (hash, "C0DEDBAD", "coded bad"); assert (rc == 0); rc = zhashx_insert (hash, "DEADF00D", "dead food"); assert (rc == 0); assert (zhashx_size (hash) == 4); // Look for existing items item = (char *) zhashx_lookup (hash, "DEADBEEF"); assert (streq (item, "dead beef")); item = (char *) zhashx_lookup (hash, "ABADCAFE"); assert (streq (item, "a bad cafe")); item = (char *) zhashx_lookup (hash, "C0DEDBAD"); assert (streq (item, "coded bad")); item = (char *) zhashx_lookup (hash, "DEADF00D"); assert (streq (item, "dead food")); // Look for non-existent items item = (char *) zhashx_lookup (hash, "foo"); assert (item == NULL); // Try to insert duplicate items rc = zhashx_insert (hash, "DEADBEEF", "foo"); assert (rc == -1); item = (char *) zhashx_lookup (hash, "DEADBEEF"); assert (streq (item, "dead beef")); // Some rename tests // Valid rename, key is now LIVEBEEF rc = zhashx_rename (hash, "DEADBEEF", "LIVEBEEF"); assert (rc == 0); item = (char *) zhashx_lookup (hash, "LIVEBEEF"); assert (streq (item, "dead beef")); // Trying to rename an unknown item to a non-existent key rc = zhashx_rename (hash, "WHATBEEF", "NONESUCH"); assert (rc == -1); // Trying to rename an unknown item to an existing key rc = zhashx_rename (hash, "WHATBEEF", "LIVEBEEF"); assert (rc == -1); item = (char *) zhashx_lookup (hash, "LIVEBEEF"); assert (streq (item, "dead beef")); // Trying to rename an existing item to another existing item rc = zhashx_rename (hash, "LIVEBEEF", "ABADCAFE"); assert (rc == -1); item = (char *) zhashx_lookup (hash, "LIVEBEEF"); assert (streq (item, "dead beef")); item = (char *) zhashx_lookup (hash, "ABADCAFE"); assert (streq (item, "a bad cafe")); // Test keys method zlistx_t *keys = zhashx_keys (hash); assert (zlistx_size (keys) == 4); zlistx_destroy (&keys); zlistx_t *values = zhashx_values(hash); assert (zlistx_size (values) == 4); zlistx_destroy (&values); // Test dup method zhashx_t *copy = zhashx_dup (hash); assert (zhashx_size (copy) == 4); item = (char *) zhashx_lookup (copy, "LIVEBEEF"); assert (item); assert (streq (item, "dead beef")); zhashx_destroy (©); // Test pack/unpack methods zframe_t *frame = zhashx_pack (hash); copy = zhashx_unpack (frame); zframe_destroy (&frame); assert (zhashx_size (copy) == 4); item = (char *) zhashx_lookup (copy, "LIVEBEEF"); assert (item); assert (streq (item, "dead beef")); zhashx_destroy (©); // Test save and load zhashx_comment (hash, "This is a test file"); zhashx_comment (hash, "Created by %s", "czmq_selftest"); zhashx_save (hash, ".cache"); copy = zhashx_new (); assert (copy); zhashx_load (copy, ".cache"); item = (char *) zhashx_lookup (copy, "LIVEBEEF"); assert (item); assert (streq (item, "dead beef")); zhashx_destroy (©); zsys_file_delete (".cache"); // Delete a item zhashx_delete (hash, "LIVEBEEF"); item = (char *) zhashx_lookup (hash, "LIVEBEEF"); assert (item == NULL); assert (zhashx_size (hash) == 3); // Check that the queue is robust against random usage struct { char name [100]; bool exists; } testset [200]; memset (testset, 0, sizeof (testset)); int testmax = 200, testnbr, iteration; srandom ((unsigned) time (NULL)); for (iteration = 0; iteration < 25000; iteration++) { testnbr = randof (testmax); if (testset [testnbr].exists) { item = (char *) zhashx_lookup (hash, testset [testnbr].name); assert (item); zhashx_delete (hash, testset [testnbr].name); testset [testnbr].exists = false; } else { sprintf (testset [testnbr].name, "%x-%x", rand (), rand ()); if (zhashx_insert (hash, testset [testnbr].name, "") == 0) testset [testnbr].exists = true; } } // Test 10K lookups for (iteration = 0; iteration < 10000; iteration++) item = (char *) zhashx_lookup (hash, "DEADBEEFABADCAFE"); // Destructor should be safe to call twice zhashx_destroy (&hash); zhashx_destroy (&hash); assert (hash == NULL); // Test autofree; automatically copies and frees string values hash = zhashx_new (); assert (hash); zhashx_autofree (hash); char value [255]; strcpy (value, "This is a string"); rc = zhashx_insert (hash, "key1", value); assert (rc == 0); strcpy (value, "Ring a ding ding"); rc = zhashx_insert (hash, "key2", value); assert (rc == 0); assert (streq ((char *) zhashx_lookup (hash, "key1"), "This is a string")); assert (streq ((char *) zhashx_lookup (hash, "key2"), "Ring a ding ding")); zhashx_destroy (&hash); // @end printf ("OK\n"); }
/// // Remove an item specified by key from the hash table. If there was no such // item, this function does nothing. void QZhashx::deleteNoConflict (const void *key) { zhashx_delete (self, key); }