ENGINE_ERROR_CODE assoc_prefix_link(struct default_engine *engine, hash_item *it, const size_t item_size, prefix_t **pfx_item) { assert(it->nprefix == 0); const char *key = item_get_key(it); size_t nkey = it->nkey; int prefix_depth = 0; int i = 0; char *token; prefix_t *pt = NULL; prefix_t_list_elem prefix_list[DEFAULT_PREFIX_MAX_DEPTH]; // prefix discovering: we don't even know prefix existence at this time while ((token = memchr(key + i + 1, engine->config.prefix_delimiter, nkey - i - 1)) != NULL) { i = token - key; prefix_list[prefix_depth].nprefix = i; prefix_depth++; if (prefix_depth >= DEFAULT_PREFIX_MAX_DEPTH) { break; } } if (prefix_depth == 0) { pt = root_pt; time(&pt->create_time); it->nprefix = nkey; } else { for (i = prefix_depth - 1; i >= 0; i--) { prefix_list[i].hash = engine->server.core->hash(key, prefix_list[i].nprefix, 0); pt = assoc_prefix_find(engine, prefix_list[i].hash, key, prefix_list[i].nprefix); if (pt != NULL) break; } if (i < (prefix_depth - 1)) { if (prefix_depth == 1) { if (!mc_isvalidname(key, prefix_list[0].nprefix)) { return ENGINE_PREFIX_ENAME; /* Invalid prefix name */ } } // need building prefixes if (pt != NULL && i >= 0) { prefix_list[i].pt = pt; // i >= 0 } for (int j = i + 1; j < prefix_depth; j++) { pt = (prefix_t*)malloc(sizeof(prefix_t) + prefix_list[j].nprefix + 1); if (pt == NULL) { for (j = j - 1; j >= i + 1; j--) { assert(prefix_list[j].pt != NULL); _prefix_delete(engine, prefix_list[j].hash, key, prefix_list[j].nprefix); } return ENGINE_ENOMEM; } // building a prefix_t memset(pt, 0, sizeof(prefix_t)); memcpy(pt + 1, key, prefix_list[j].nprefix); memcpy((char*)pt+sizeof(prefix_t)+prefix_list[j].nprefix, "\0", 1); pt->nprefix = prefix_list[j].nprefix; pt->parent_prefix = (j == 0 ? root_pt : prefix_list[j-1].pt); time(&pt->create_time); // registering allocated prefixes to prefix hastable _prefix_insert(engine, prefix_list[j].hash, pt); prefix_list[j].pt = pt; } } // update item information about prefix length it->nprefix = pt->nprefix; } assert(pt != NULL); // update prefix information if ((it->iflag & ITEM_IFLAG_LIST) != 0) { pt->list_hash_items++; pt->list_hash_items_bytes += item_size; } else if ((it->iflag & ITEM_IFLAG_SET) != 0) { pt->set_hash_items++; pt->set_hash_items_bytes += item_size; } else if ((it->iflag & ITEM_IFLAG_BTREE) != 0) { pt->btree_hash_items++; pt->btree_hash_items_bytes += item_size; } else { pt->hash_items++; pt->hash_items_bytes += item_size; } #if 0 // might be used later if (1) { curr_pt = pt->parent_prefix; while (curr_pt != NULL) { curr_pt->tot_hash_items++; curr_pt->tot_hash_items_bytes += item_size; curr_pt = curr_pt->parent_prefix; } } #endif *pfx_item = pt; return ENGINE_SUCCESS; }
ENGINE_ERROR_CODE assoc_prefix_link(struct default_engine *engine, hash_item *it, const size_t item_size) { const char *key = item_get_key(it); size_t nkey = it->nkey; int prefix_depth = 0; int i = 0; char *token; prefix_t *pt = NULL; prefix_t_list_elem prefix_list[DEFAULT_PREFIX_MAX_DEPTH]; // prefix discovering: we don't even know prefix existence at this time while ((token = memchr(key+i+1, engine->config.prefix_delimiter, nkey-i-1)) != NULL) { i = token - key; prefix_list[prefix_depth].nprefix = i; prefix_depth++; if (prefix_depth >= DEFAULT_PREFIX_MAX_DEPTH) { break; } } if (prefix_depth == 0) { pt = root_pt; time(&pt->create_time); /* save prefix pointer in hash_item */ it->pfxptr = pt; } else { for (i = prefix_depth - 1; i >= 0; i--) { prefix_list[i].hash = engine->server.core->hash(key, prefix_list[i].nprefix, 0); pt = assoc_prefix_find(engine, prefix_list[i].hash, key, prefix_list[i].nprefix); if (pt != NULL) break; } if (i < (prefix_depth - 1)) { if (prefix_depth == 1) { if (!mc_isvalidname(key, prefix_list[0].nprefix)) { return ENGINE_PREFIX_ENAME; /* Invalid prefix name */ } } // need building prefixes if (pt != NULL && i >= 0) { prefix_list[i].pt = pt; // i >= 0 } for (int j = i + 1; j < prefix_depth; j++) { pt = (prefix_t*)malloc(sizeof(prefix_t) + prefix_list[j].nprefix + 1); if (pt == NULL) { for (j = j - 1; j >= i + 1; j--) { assert(prefix_list[j].pt != NULL); _prefix_delete(engine, prefix_list[j].hash, key, prefix_list[j].nprefix); } return ENGINE_ENOMEM; } // building a prefix_t memset(pt, 0, sizeof(prefix_t)); memcpy(pt + 1, key, prefix_list[j].nprefix); memcpy((char*)pt+sizeof(prefix_t)+prefix_list[j].nprefix, "\0", 1); pt->nprefix = prefix_list[j].nprefix; if (PREFIX_IS_RSVD(key, pt->nprefix)) { pt->internal = 1; /* internal prefix */ } pt->parent_prefix = (j == 0 ? root_pt : prefix_list[j-1].pt); time(&pt->create_time); // registering allocated prefixes to prefix hastable _prefix_insert(engine, prefix_list[j].hash, pt); prefix_list[j].pt = pt; } } /* save prefix pointer in hash_item */ it->pfxptr = pt; } assert(pt != NULL); /* update prefix information */ int item_type = GET_ITEM_TYPE(it); pt->items_count[item_type] += 1; pt->items_bytes[item_type] += item_size; pt->total_count_exclusive += 1; pt->total_bytes_exclusive += item_size; #if 0 // might be used later if (1) { prefix_t *curr_pt = pt->parent_prefix; while (curr_pt != NULL) { curr_pt->total_count_inclusive += 1; curr_pt->total_bytes_inclusive += item_size; curr_pt = curr_pt->parent_prefix; } } #endif return ENGINE_SUCCESS; }