int32_t drn_val_hash_cmp(const void * valA, const void * valB) { drn_writer_key_t * v1 = (drn_writer_key_t * ) valA; drn_writer_key_t * v2 = (drn_writer_key_t * ) valB; uint32_t h1 = drn_oat_hash(v1->value, (uint32_t) strlen(v1->value))%DRN_HASH_MAP_SIZE; uint32_t h2 = drn_oat_hash(v2->value, (uint32_t) strlen(v2->value))%DRN_HASH_MAP_SIZE; if (h1 > h2) return 1; if (h1 < h2) return -1; return 0; }
uint64_t drn_count_matching_chunks(drn_t * cache, drn_map_id_t map_id, const char * key_value) { const drn_map_t * h = cache->maps + map_id; const drn_hash_cell_t * hash_map = h->hash; const drn_hash_desc_t * hash_descriptors = h->descriptors; const char * hash_values = h->value_strings; uint32_t cell_idx = drn_oat_hash((void * )key_value, (uint32_t) strlen(key_value))%DRN_HASH_MAP_SIZE; uint64_t count = 0; uint64_t d_idx; for (d_idx = 0; d_idx < hash_map[cell_idx].count; ++d_idx) { if (!strcmp(hash_values + hash_descriptors[hash_map[cell_idx].offset + d_idx].key_value_offset, key_value)) ++count; } return count; }
int32_t drn_close_writer(drn_writer_t *cache) { drn_header_container_t header; drn_map_container_t * maps = (drn_map_container_t *) ALLOCATE(sbcount(cache->maps) * sizeof(drn_map_container_t)); uint64_t m_idx; uint64_t i; size_t bytes; for (m_idx=0; m_idx < sbcount(cache->maps); ++m_idx) { drn_writer_map_t * map = cache->maps + m_idx; drn_hash_cell_t * hash_map = (drn_hash_cell_t *) ALLOCATE(DRN_HASH_MAP_SIZE * sizeof (drn_hash_cell_t)); uint64_t hc_idx; uint64_t chunk_count = 0; uint64_t values_size = 0; drn_writer_key_t * key_array = map->keys; uint64_t k_idx; drn_hash_desc_t * descriptors; char * values_string_array; uint32_t desc_offset_cntr; uint32_t value_strings_offset_cntr; for (hc_idx = 0; hc_idx < DRN_HASH_MAP_SIZE; ++hc_idx) { hash_map[hc_idx].offset = 0; hash_map[hc_idx].count = 0; } /* count Es + sum VV lengths */ for (k_idx = 0; k_idx < sbcount(map->keys); ++k_idx) { drn_writer_key_t * value = map->keys + k_idx; chunk_count += sbcount(value->descriptors); values_size += strlen(value->value)+1; } /* Allocate Es */ descriptors = (drn_hash_desc_t*) ALLOCATE((size_t) chunk_count * sizeof(drn_hash_desc_t)); /* Allocate Vv */ values_string_array = (char *) ALLOCATE((size_t) values_size * sizeof(char)); /* Sort Vs */ qsort(key_array, sbcount(map->keys), sizeof(drn_writer_key_t), drn_val_hash_cmp); /* For each V */ desc_offset_cntr = 0; value_strings_offset_cntr = 0; for (k_idx = 0; k_idx < sbcount(map->keys); ++k_idx) { uint32_t hash = drn_oat_hash(key_array[k_idx].value, (uint32_t) strlen(key_array[k_idx].value))%DRN_HASH_MAP_SIZE; uint64_t * chunk_ids = key_array[k_idx].descriptors; uint64_t d_idx; /* Fill H */ hash_map[hash].offset = desc_offset_cntr; hash_map[hash].count = sbcount(key_array[k_idx].descriptors); /* Fill Vv */ memcpy(values_string_array + value_strings_offset_cntr, key_array[k_idx].value, strlen(key_array[k_idx].value)+1); /* fill E */ qsort(chunk_ids, sbcount(key_array[k_idx].descriptors), sizeof(uint64_t), drn_uint64_cmp); for (d_idx = 0; d_idx < sbcount(key_array[k_idx].descriptors); ++d_idx) { descriptors[desc_offset_cntr].chunk_id = chunk_ids[d_idx]; descriptors[desc_offset_cntr].key_value_offset = value_strings_offset_cntr; ++desc_offset_cntr; } /* Increment offsets */ value_strings_offset_cntr += (uint32_t) strlen(key_array[k_idx].value)+1; } /* Write hash array as desc */ drn_writer_add_chunk(cache, hash_map, sizeof(drn_hash_cell_t) * DRN_HASH_MAP_SIZE); maps[m_idx].hash_chunk_id = drn_writer_get_last_chunk_id(cache); /* Write hash name as desc */ drn_writer_add_chunk(cache, map->name, strlen(map->name) + 1); maps[m_idx].name_chunk_id = drn_writer_get_last_chunk_id(cache); /* Write value string array as desc */ drn_writer_add_chunk(cache, descriptors, sizeof(drn_hash_desc_t) * chunk_count); maps[m_idx].descriptors_chunk_id = drn_writer_get_last_chunk_id(cache); /* Write desc array as desc */ drn_writer_add_chunk(cache, values_string_array, values_size); maps[m_idx].value_strings_chunk_id = drn_writer_get_last_chunk_id(cache); FREE(hash_map); FREE(descriptors); FREE(values_string_array); } drn_writer_add_chunk(cache, maps, sizeof(drn_map_container_t) * sbcount(cache->maps)); FREE(maps); header.version = cache->version; memcpy(header.description, cache->description, 256); header.index_offset = cache->desc_start_offset + cache->desc_end_offset; header.chunk_count = cache->chunk_count; header.maps_chunk_id = drn_writer_get_last_chunk_id(cache); LSEEK(cache->fd, 0L, SEEK_SET); bytes = WRITE(cache->fd, &header, sizeof(drn_header_container_t)); if (bytes != sizeof(drn_header_container_t)) return -1; LSEEK(cache->fd, cache->desc_start_offset + cache->desc_end_offset, SEEK_SET); bytes = WRITE(cache->fd, cache->descriptors, WRITE_COUNT_CAST (sizeof(drn_desc_t) * cache->chunk_count)); if (bytes != sizeof(drn_desc_t) * cache->chunk_count) return -1; if (CLOSE(cache->fd) == -1) return -1; for (i = 0; i < sbcount(cache->maps); ++i) { drn_writer_map_t * map = cache->maps + i; uint64_t j; for (j = 0; j < sbcount(map->keys); ++j) { drn_writer_key_t * value = map->keys + j; sbfree(value->descriptors); FREE(value->value); } sbfree(map->keys); FREE(map->name); } sbfree(cache->maps); sbfree(cache->descriptors); return 0; }