/** * Initializer * @arg config The configuration * @arg vacuum Should vacuuming be enabled. True unless in a * test or embedded environment using filtmgr_vacuum() * @arg mgr Output, resulting manager. * @return 0 on success. */ int init_filter_manager(bloom_config *config, int vacuum, bloom_filtmgr **mgr) { // Allocate a new object bloom_filtmgr *m = *mgr = calloc(1, sizeof(bloom_filtmgr)); // Copy the config m->config = config; // Initialize the locks pthread_mutex_init(&m->write_lock, NULL); INIT_BLOOM_SPIN(&m->clients_lock); INIT_BLOOM_SPIN(&m->pending_lock); // Allocate storage for the art trees art_tree *trees = calloc(2, sizeof(art_tree)); m->filter_map = trees; m->alt_filter_map = trees+1; // Allocate the initial art tree int res = init_art_tree(m->filter_map); if (res) { syslog(LOG_ERR, "Failed to allocate filter map!"); free(m); return -1; } // Discover existing filters load_existing_filters(m); // Initialize the alternate map res = art_copy(m->alt_filter_map, m->filter_map); if (res) { syslog(LOG_ERR, "Failed to copy filter map to alternate!"); destroy_filter_manager(m); return -1; } // Start the vacuum thread m->should_run = vacuum; if (vacuum && pthread_create(&m->vacuum_thread, NULL, filtmgr_thread_main, m)) { perror("Failed to start vacuum thread!"); destroy_filter_manager(m); return 1; } // Done return 0; }
/** * Initializes a bloom filter wrapper. * @arg config The configuration to use * @arg filter_name The name of the filter * @arg discover Should existing data files be discovered. Otherwise * they will be faulted in on-demand. * @arg filter Output parameter, the new filter * @return 0 on success */ int init_bloom_filter(bloom_config *config, char *filter_name, int discover, bloom_filter **filter) { // Allocate the buffers bloom_filter *f = *filter = calloc(1, sizeof(bloom_filter)); // Store the things f->config = config; f->filter_name = strdup(filter_name); // Copy filter configs f->filter_config.initial_capacity = config->initial_capacity; f->filter_config.capacity = config->initial_capacity; f->filter_config.default_probability = config->default_probability; f->filter_config.scale_size = config->scale_size; f->filter_config.probability_reduction = config->probability_reduction; f->filter_config.in_memory = config->in_memory; // Get the folder name char *folder_name = NULL; int res; res = asprintf(&folder_name, FILTER_FOLDER_NAME, f->filter_name); assert(res != -1); // Compute the full path f->full_path = join_path(config->data_dir, folder_name); free(folder_name); // Initialize the locks INIT_BLOOM_SPIN(&f->counter_lock); pthread_mutex_init(&f->sbf_lock, NULL); // Try to create the folder path res = mkdir(f->full_path, 0755); if (res && errno != EEXIST) { syslog(LOG_ERR, "Failed to create filter directory '%s'. Err: %d [%d]", f->full_path, res, errno); return res; } // Read in the filter_config char *config_name = join_path(f->full_path, (char*)CONFIG_FILENAME); res = filter_config_from_filename(config_name, &f->filter_config); free(config_name); if (res && res != -ENOENT) { syslog(LOG_ERR, "Failed to read filter '%s' configuration. Err: %d [%d]", f->filter_name, res, errno); return res; } // Discover the existing filters if we need to res = 0; if (discover) { res = thread_safe_fault(f); if (res) { syslog(LOG_ERR, "Failed to fault in the filter '%s'. Err: %d", f->filter_name, res); } } // Trigger a flush on first instantiation. This will create // a new ini file for first time filters. if (!res) { res = bloomf_flush(f); } return res; }