Exemplo n.º 1
0
/**
 * Should be invoked by clients when they no longer
 * need to make use of the filter manager. This
 * allows the vacuum thread to cleanup garbage state.
 * @arg mgr The manager
 */
void filtmgr_client_leave(bloom_filtmgr *mgr) {
    // Get a reference to ourself
    pthread_t id = pthread_self();

    // Critical section
    LOCK_BLOOM_SPIN(&mgr->clients_lock);

    // Look for our ID, and update the version
    // This is O(n), but N is small and its done infrequently
    filtmgr_client **last_next = &mgr->clients;
    filtmgr_client *cl = mgr->clients;
    while (cl) {
        if (cl->id == id) {
            // Set the last prev pointer to skip the current entry
            *last_next = cl->next;

            // Cleanup the memory associated
            free(cl);
            break;
        }
        last_next = &cl->next;
        cl = cl->next;
    }
    UNLOCK_BLOOM_SPIN(&mgr->clients_lock);
}
Exemplo n.º 2
0
/**
 * Should be invoked periodically by client threads to allow
 * the vacuum thread to cleanup garbage state. It should also
 * be called before making other calls into the filter manager
 * so that it is aware of a client making use of the current
 * state.
 * @arg mgr The manager
 */
void filtmgr_client_checkpoint(bloom_filtmgr *mgr) {
    // Get a reference to ourself
    pthread_t id = pthread_self();

    // Look for our ID, and update the version
    // This is O(n), but N is small and its done infrequently
    filtmgr_client *cl = mgr->clients;
    while (cl) {
        if (cl->id == id) {
            cl->vsn = mgr->vsn;
            return;
        }
        cl = cl->next;
    }

    // If we make it here, we are not a client yet
    // so we need to safely add ourself
    cl = malloc(sizeof(filtmgr_client));
    cl->id = id;
    cl->vsn = mgr->vsn;

    // Critical section for the flip
    LOCK_BLOOM_SPIN(&mgr->clients_lock);

    cl->next = mgr->clients;
    mgr->clients = cl;

    UNLOCK_BLOOM_SPIN(&mgr->clients_lock);
}
Exemplo n.º 3
0
/**
 * Creates a new filter of the given name and parameters.
 * @arg filter_name The name of the filter
 * @arg custom_config Optional, can be null. Configs that override the defaults.
 * @return 0 on success, -1 if the filter already exists.
 * -2 for internal error. -3 if there is a pending delete.
 */
int filtmgr_create_filter(bloom_filtmgr *mgr, char *filter_name, bloom_config *custom_config) {
    int res = 0;
    pthread_mutex_lock(&mgr->write_lock);

    // Bail if the filter already exists.
    bloom_filter_wrapper *filt = find_filter(mgr, filter_name);
    if (filt) {
        res = (filt->is_active) ? -1 : -3;
        goto LEAVE;
    }

    // Scan the pending delete queue
    LOCK_BLOOM_SPIN(&mgr->pending_lock);
    if (mgr->pending_deletes) {
        bloom_filter_list *node = mgr->pending_deletes;
        while (node) {
            if (!strcmp(node->filter_name, filter_name)) {
                res = -3; // Pending delete
                UNLOCK_BLOOM_SPIN(&mgr->pending_lock);
                goto LEAVE;
            }
            node = node->next;
        }
    }
    UNLOCK_BLOOM_SPIN(&mgr->pending_lock);

    // Use a custom config if provided, else the default
    bloom_config *config = (custom_config) ? custom_config : mgr->config;

    // Add the filter to the new version
    if (add_filter(mgr, filter_name, config, 1, 1)) {
        res = -2; // Internal error
    }

LEAVE:
    pthread_mutex_unlock(&mgr->write_lock);
    return res;
}
Exemplo n.º 4
0
/**
 * Adds a key to the given filter
 * @arg filter The filter to add to
 * @arg key The key to add
 * @return 0 if not added, 1 if added.
 */
int bloomf_add(bloom_filter *filter, char *key) {
    if (!filter->sbf) {
        if (thread_safe_fault(filter) != 0) return -1;
    }

    // Add the SBF
    int res = sbf_add((bloom_sbf*)filter->sbf, key);

    // Safely update the counters
    LOCK_BLOOM_SPIN(&filter->counter_lock);
    if (res == 1)
        filter->counters.set_hits += 1;
    else if (res == 0)
        filter->counters.set_misses += 1;
    UNLOCK_BLOOM_SPIN(&filter->counter_lock);

    return res;
}
Exemplo n.º 5
0
/**
 * Clears the pending deletes
 */
static void clear_pending_deletes(bloom_filtmgr *mgr) {
    // Get a reference to the head
    bloom_filter_list *pending = mgr->pending_deletes;
    if (!pending) return;

    // filter the pending list to NULL safely
    LOCK_BLOOM_SPIN(&mgr->pending_lock);
    mgr->pending_deletes = NULL;
    UNLOCK_BLOOM_SPIN(&mgr->pending_lock);

    // Free the nodes
    bloom_filter_list *next;
    while (pending) {
        free(pending->filter_name);
        next = pending->next;
        free(pending);
        pending = next;
    }
}
Exemplo n.º 6
0
/**
 * Updates the pending deletes list with a list of pending deletes
 */
static void mark_pending_deletes(bloom_filtmgr *mgr, unsigned long long min_vsn) {
    bloom_filter_list *tmp, *pending = NULL;

    // Add each delete
    filter_list *delta = mgr->delta;
    while (delta) {
        if (delta->vsn <= min_vsn && delta->type == DELETE) {
            tmp = malloc(sizeof(bloom_filter_list));
            tmp->filter_name = strdup(delta->filter->filter->filter_name);
            tmp->next = pending;
            pending = tmp;
        }
        delta = delta->next;
    }

    LOCK_BLOOM_SPIN(&mgr->pending_lock);
    mgr->pending_deletes = pending;
    UNLOCK_BLOOM_SPIN(&mgr->pending_lock);
}