static void handle_flush_cmd(bloom_conn_handler *handle, char *args, int args_len) { // If we have a specfic filter, use filt_cmd if (args) { handle_filt_cmd(handle, args, args_len, filtmgr_flush_filter); return; } // List all the filters bloom_filter_list_head *head; int res = filtmgr_list_filters(handle->mgr, NULL, &head); if (res != 0) { INTERNAL_ERROR(); return; } // Flush all, ignore errors since // filters might get deleted in the process bloom_filter_list *node = head->head; while (node) { filtmgr_flush_filter(handle->mgr, node->filter_name); node = node->next; } // Respond handle_client_resp(handle->conn, (char*)DONE_RESP, DONE_RESP_LEN); // Cleanup filtmgr_cleanup_list(head); }
END_TEST START_TEST(test_mgr_list_cold) { bloom_config config; int res = config_from_filename(NULL, &config); fail_unless(res == 0); bloom_filtmgr *mgr; res = init_filter_manager(&config, &mgr); fail_unless(res == 0); res = filtmgr_create_filter(mgr, "zab6", NULL); fail_unless(res == 0); res = filtmgr_create_filter(mgr, "zab7", NULL); fail_unless(res == 0); bloom_filter_list_head *head; res = filtmgr_list_cold_filters(mgr, &head); fail_unless(res == 0); fail_unless(head->size == 0); // Check the keys in one, so that it stays hot char *keys[] = {"hey","there","person"}; char result[] = {0, 0, 0}; res = filtmgr_set_keys(mgr, "zab6", (char**)&keys, 3, (char*)&result); fail_unless(res == 0); fail_unless(result[0]); fail_unless(result[1]); fail_unless(result[2]); // Check cold again res = filtmgr_list_cold_filters(mgr, &head); fail_unless(res == 0); fail_unless(head->size == 1); int has_zab6 = 0; int has_zab7 = 0; bloom_filter_list *node = head->head; while (node) { if (strcmp(node->filter_name, "zab6") == 0) has_zab6 = 1; else if (strcmp(node->filter_name, "zab7") == 0) has_zab7 = 1; node = node->next; } fail_unless(!has_zab6); fail_unless(has_zab7); res = filtmgr_drop_filter(mgr, "zab6"); fail_unless(res == 0); res = filtmgr_drop_filter(mgr, "zab7"); fail_unless(res == 0); filtmgr_cleanup_list(head); res = destroy_filter_manager(mgr); fail_unless(res == 0); }
END_TEST START_TEST(test_mgr_list_prefix) { bloom_config config; int res = config_from_filename(NULL, &config); fail_unless(res == 0); bloom_filtmgr *mgr; res = init_filter_manager(&config, 0, &mgr); fail_unless(res == 0); res = filtmgr_create_filter(mgr, "bar1", NULL); fail_unless(res == 0); res = filtmgr_create_filter(mgr, "bar2", NULL); fail_unless(res == 0); res = filtmgr_create_filter(mgr, "zyx", NULL); fail_unless(res == 0); bloom_filter_list_head *head; res = filtmgr_list_filters(mgr, "bar", &head); fail_unless(res == 0); fail_unless(head->size == 2); int has_bar1 = 0; int has_bar2 = 0; bloom_filter_list *node = head->head; while (node) { if (strcmp(node->filter_name, "bar1") == 0) has_bar1 = 1; else if (strcmp(node->filter_name, "bar2") == 0) has_bar2 = 1; node = node->next; } fail_unless(has_bar1); fail_unless(has_bar2); res = filtmgr_drop_filter(mgr, "bar1"); fail_unless(res == 0); res = filtmgr_drop_filter(mgr, "bar2"); fail_unless(res == 0); res = filtmgr_drop_filter(mgr, "zyx"); fail_unless(res == 0); filtmgr_cleanup_list(head); res = destroy_filter_manager(mgr); fail_unless(res == 0); }
static void handle_list_cmd(bloom_conn_handler *handle, char *args, int args_len) { // cheat gcc to compile without warnings (void)args_len; // List all the filters bloom_filter_list_head *head; int res = filtmgr_list_filters(handle->mgr, args, &head); if (res != 0) { INTERNAL_ERROR(); return; } // Allocate buffers for the responses int num_out = (head->size+2); char** output_bufs = malloc(num_out * sizeof(char*)); int* output_bufs_len = malloc(num_out * sizeof(int)); // Setup the START/END lines output_bufs[0] = (char*)&START_RESP; output_bufs_len[0] = START_RESP_LEN; output_bufs[head->size+1] = (char*)&END_RESP; output_bufs_len[head->size+1] = END_RESP_LEN; // Generate the responses char *resp; bloom_filter_list *node = head->head; for (int i=0; i < head->size; i++) { res = filtmgr_filter_cb(handle->mgr, node->filter_name, list_filter_cb, &resp); if (res == 0) { output_bufs[i+1] = resp; output_bufs_len[i+1] = strlen(resp); } else { // Skip this output output_bufs[i+1] = NULL; output_bufs_len[i+1] = 0; } node = node->next; } // Write the response send_client_response(handle->conn, output_bufs, output_bufs_len, num_out); // Cleanup for (int i=1; i <= head->size; i++) if(output_bufs[i]) free(output_bufs[i]); free(output_bufs); free(output_bufs_len); filtmgr_cleanup_list(head); }
END_TEST START_TEST(test_mgr_list_no_filters) { bloom_config config; int res = config_from_filename(NULL, &config); fail_unless(res == 0); bloom_filtmgr *mgr; res = init_filter_manager(&config, &mgr); fail_unless(res == 0); bloom_filter_list_head *head; res = filtmgr_list_filters(mgr, &head); fail_unless(res == 0); fail_unless(head->size == 0); filtmgr_cleanup_list(head); res = destroy_filter_manager(mgr); fail_unless(res == 0); }
static void* flush_thread_main(void *in) { bloom_config *config; bloom_filtmgr *mgr; int *should_run; UNPACK_ARGS(); // Perform the initial checkpoint with the manager filtmgr_client_checkpoint(mgr); syslog(LOG_INFO, "Flush thread started. Interval: %d seconds.", config->flush_interval); unsigned int ticks = 0; while (*should_run) { sleep(1); filtmgr_client_checkpoint(mgr); if ((++ticks % config->flush_interval) == 0 && *should_run) { // List all the filters syslog(LOG_INFO, "Scheduled flush started."); bloom_filter_list_head *head; int res = filtmgr_list_filters(mgr, &head); if (res != 0) { syslog(LOG_WARNING, "Failed to list filters for flushing!"); continue; } // Flush all, ignore errors since // filters might get deleted in the process bloom_filter_list *node = head->head; while (node) { filtmgr_flush_filter(mgr, node->filter_name); node = node->next; } // Cleanup filtmgr_cleanup_list(head); } } return NULL; }
static void* unmap_thread_main(void *in) { bloom_config *config; bloom_filtmgr *mgr; int *should_run; UNPACK_ARGS(); // Perform the initial checkpoint with the manager filtmgr_client_checkpoint(mgr); syslog(LOG_INFO, "Cold unmap thread started. Interval: %d seconds.", config->cold_interval); unsigned int ticks = 0; while (*should_run) { sleep(1); filtmgr_client_checkpoint(mgr); if ((++ticks % config->cold_interval) == 0 && *should_run) { // List the cold filters syslog(LOG_INFO, "Cold unmap started."); bloom_filter_list_head *head; int res = filtmgr_list_cold_filters(mgr, &head); if (res != 0) { continue; } // Close the filters, save memory syslog(LOG_INFO, "Cold filter count: %d", head->size); bloom_filter_list *node = head->head; while (node) { syslog(LOG_INFO, "Unmapping filter '%s' for being cold.", node->filter_name); filtmgr_unmap_filter(mgr, node->filter_name); node = node->next; } // Cleanup filtmgr_cleanup_list(head); } } return NULL; }
static void handle_get_cmd(bloom_conn_handler *handle, char *args, int args_len) { #define CHECK_KEY_ERR() { \ handle_client_err(handle->conn, (char*)&KEY_NEEDED, FILT_KEY_NEEDED_LEN); \ return; \ } // If we have no args, complain. if (!args) CHECK_KEY_ERR(); // List all the filters bloom_filter_list_head *head; int res = filtmgr_list_filters(handle->mgr, NULL, &head); if (res != 0) { INTERNAL_ERROR(); return; } // setup list node bloom_filter_list *node; // Scan all the keys char *key = args; int key_len = args_len; // Parse any options char *curr_key = key; int index = 0; // count filters (segmets) int filters_count = 0; node = head->head; while(node) { filters_count++; node = node->next; } // count keys int keys_count = 1; for(int i=0; i<args_len; i++) if(args[i] == ' ') keys_count++; // Setup the buffers char *key_buf[keys_count]; char result_buf[keys_count]; // result matrix char *key_filter_mat[keys_count][filters_count]; memset(key_filter_mat, 0, sizeof(key_filter_mat)); // counter for positive rezults int key_filter_len[keys_count]; memset(key_filter_len, 0, sizeof(key_filter_len)); node = head->head; while(node) { int j = 0; // Check buffer of keys #define REQUEST_BUF() { \ int err = filtmgr_check_keys( \ handle->mgr, \ node->filter_name, \ (char**)&key_buf, \ index, \ (char*)&result_buf); \ if (err) { \ INTERNAL_ERROR(); \ return; \ }; \ for(int i=0; i<index; i++, j++) { \ if(result_buf[i] == 1) \ key_filter_mat[j][key_filter_len[j]++] = node->filter_name; \ }; \ index = 0; \ } #define HAS_ANOTHER_KEY() (curr_key && *curr_key != '\0') while (HAS_ANOTHER_KEY()) { // Adds a zero terminator to the current key, scans forward buffer_after_terminator(key, key_len, ' ', &key, &key_len); // Set the key key_buf[index] = curr_key; // Advance to the next key curr_key = key; // If we have filled the buffer, check now if (index++ == MULTI_OP_SIZE) REQUEST_BUF(); } // Handle any remaining keys if (index) REQUEST_BUF(); // revert args termintators back to \32 because buffer_affter_terminatoir() changes it for(int i=0; i<args_len-1;i++) if(args[i]=='\0') args[i] = ' '; curr_key = key = args; key_len = args_len; index = 0; node = node->next; } // collect key names char *key_names[keys_count]; char **key_names_it = key_names; while (HAS_ANOTHER_KEY()) { *(key_names_it++) = key; buffer_after_terminator(key, key_len, ' ', &key, &key_len); curr_key = key; } // send key filters int buf_len = 1024*1024; char *send_buf = (char*) malloc(buf_len); for(int i=0; i<keys_count; i++) { strcat(send_buf, key_names[i]); int l = key_filter_len[i]-1; char *d = l>=0 ? "\t" : "\n"; strcat(send_buf, d); for(int j=0; j<=l; j++) { if(j) strcat(send_buf, "/"); strcat(send_buf, key_filter_mat[i][j]); } strcat(send_buf, "\n"); } handle_client_resp(handle->conn, send_buf, strlen(send_buf)); // Respond handle_client_resp(handle->conn, (char*)DONE_RESP, DONE_RESP_LEN); // Cleanup filtmgr_cleanup_list(head); free(send_buf); }