bool initialize_item_tap_walker(struct default_engine *engine, const void* cookie) { bool linked = false; int ii; struct tap_client *client = calloc(1, sizeof(*client)); if (client == NULL) { return false; } client->cursor.refcount = 1; /* Link the cursor! */ for (ii = 0; ii < POWER_LARGEST && !linked; ++ii) { cb_mutex_enter(&engine->items.lock); if (engine->items.heads[ii] != NULL) { /* add the item at the tail */ do_item_link_cursor(engine, &client->cursor, ii); linked = true; } cb_mutex_exit(&engine->items.lock); } engine->server.cookie->store_engine_specific(cookie, client); return true; }
void item_scrubber_main(struct default_engine *engine) { hash_item cursor; int ii; memset(&cursor, 0, sizeof(cursor)); cursor.refcount = 1; for (ii = 0; ii < POWER_LARGEST; ++ii) { bool skip = false; cb_mutex_enter(&engine->items.lock); if (engine->items.heads[ii] == NULL) { skip = true; } else { /* add the item at the tail */ do_item_link_cursor(engine, &cursor, ii); } cb_mutex_exit(&engine->items.lock); if (!skip) { item_scrub_class(engine, &cursor); } } cb_mutex_enter(&engine->scrubber.lock); engine->scrubber.stopped = time(NULL); engine->scrubber.running = false; cb_mutex_exit(&engine->scrubber.lock); }
static void *item_scubber_main(void *arg) { struct default_engine *engine = arg; hash_item cursor = { .refcount = 1 }; for (int ii = 0; ii < POWER_LARGEST; ++ii) { pthread_mutex_lock(&engine->cache_lock); bool skip = false; if (engine->items.heads[ii] == NULL) { skip = true; } else { // add the item at the tail do_item_link_cursor(engine, &cursor, ii); } pthread_mutex_unlock(&engine->cache_lock); if (!skip) { item_scrub_class(engine, &cursor); } } pthread_mutex_lock(&engine->scrubber.lock); engine->scrubber.stopped = time(NULL); engine->scrubber.running = false; pthread_mutex_unlock(&engine->scrubber.lock); return NULL; } bool item_start_scrub(struct default_engine *engine) { bool ret = false; pthread_mutex_lock(&engine->scrubber.lock); if (!engine->scrubber.running) { engine->scrubber.started = time(NULL); engine->scrubber.stopped = 0; engine->scrubber.visited = 0; engine->scrubber.cleaned = 0; engine->scrubber.running = true; pthread_t t; pthread_attr_t attr; if (pthread_attr_init(&attr) != 0 || pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0 || pthread_create(&t, &attr, item_scubber_main, engine) != 0) { engine->scrubber.running = false; } else { ret = true; } } pthread_mutex_unlock(&engine->scrubber.lock); return ret; }
static ENGINE_ERROR_CODE do_item_dcp_step(struct default_engine *engine, struct dcp_connection *connection, const void *cookie, struct dcp_message_producers *producers) { ENGINE_ERROR_CODE ret = ENGINE_DISCONNECT; while (connection->it == NULL) { if (!do_item_walk_cursor(engine, &connection->cursor, 1, item_dcp_iterfunc, connection, &ret)) { /* find next slab class to look at.. */ bool linked = false; int ii; for (ii = connection->cursor.slabs_clsid + 1; ii < POWER_LARGEST && !linked; ++ii) { if (engine->items.heads[ii] != NULL) { /* add the item at the tail */ do_item_link_cursor(engine, &connection->cursor, ii); linked = true; } } if (!linked) { break; } } } if (connection->it != NULL) { rel_time_t current_time = engine->server.core->get_current_time(); rel_time_t exptime = connection->it->exptime; if (exptime != 0 && exptime < current_time) { const hash_key* key = item_get_key(connection->it); ret = producers->expiration(cookie, connection->opaque, hash_key_get_client_key(key), hash_key_get_client_key_len(key), item_get_cas(connection->it), 0, 0, 0, NULL, 0); if (ret == ENGINE_SUCCESS) { do_item_unlink(engine, connection->it); do_item_release(engine, connection->it); } } else { ret = producers->mutation(cookie, connection->opaque, connection->it, 0, 0, 0, 0, NULL, 0, 0); } if (ret == ENGINE_SUCCESS) { connection->it = NULL; } } else { return ENGINE_DISCONNECT; } return ret; }
void link_dcp_walker(struct default_engine *engine, struct dcp_connection *connection) { bool linked = false; int ii; connection->cursor.refcount = 1; /* Link the cursor! */ for (ii = 0; ii < POWER_LARGEST && !linked; ++ii) { cb_mutex_enter(&engine->items.lock); if (engine->items.heads[ii] != NULL) { /* add the item at the tail */ do_item_link_cursor(engine, &connection->cursor, ii); linked = true; } cb_mutex_exit(&engine->items.lock); } }
static tap_event_t do_item_tap_walker(struct default_engine *engine, const void *cookie, item **itm, void **es, uint16_t *nes, uint8_t *ttl, uint16_t *flags, uint32_t *seqno, uint16_t *vbucket) { ENGINE_ERROR_CODE r; struct tap_client *client = engine->server.cookie->get_engine_specific(cookie); if (client == NULL) { return TAP_DISCONNECT; } *es = NULL; *nes = 0; *ttl = (uint8_t)-1; *seqno = 0; *flags = 0; *vbucket = 0; client->it = NULL; do { if (!do_item_walk_cursor(engine, &client->cursor, 1, item_tap_iterfunc, client, &r)) { /* find next slab class to look at.. */ bool linked = false; int ii; for (ii = client->cursor.slabs_clsid + 1; ii < POWER_LARGEST && !linked; ++ii) { if (engine->items.heads[ii] != NULL) { /* add the item at the tail */ do_item_link_cursor(engine, &client->cursor, ii); linked = true; } } if (!linked) { break; } } } while (client->it == NULL); *itm = client->it; return (*itm == NULL) ? TAP_DISCONNECT : TAP_MUTATION; }