Ejemplo n.º 1
0
// this is only used when this node is the first node in the cluster, and we need to create some new empty buckets.
void buckets_init(hash_t mask, struct event_base *evbase)
{
	int i;

	assert(_evbase == NULL);
	assert(evbase);
	_evbase = evbase;
	
	assert(_mask == 0);
	assert(mask >= _mask);
	_mask = mask;
	
	assert(_mask > 0);
	_buckets = calloc(_mask+1, sizeof(bucket_t *));
	assert(_buckets);

	assert(_primary_buckets == 0);
	assert(_secondary_buckets == 0);
	
	
	
	// for starters we will need to create a bucket for each hash.
	for (i=0; i<=_mask; i++) {
		_buckets[i] = bucket_new(i);

		_primary_buckets ++;
		_buckets[i]->level = 0;

		// send out a message to all connected clients, to let them know that the buckets have changed.
		update_hashmasks(_buckets[i]); // all_hashmask(i, 0);
	}

	// indicate that we have buckets that do not have backup copies on other nodes.
	_nobackup_buckets = _mask + 1;
}
Ejemplo n.º 2
0
/*
 * heap_buckets_init -- (internal) initializes bucket instances
 */
int
heap_buckets_init(struct palloc_heap *heap)
{
	struct heap_rt *h = heap->rt;

	for (uint8_t i = 0; i < MAX_ALLOCATION_CLASSES; ++i) {
		struct alloc_class *c = alloc_class_by_id(h->alloc_classes, i);
		if (c != NULL) {
			if (heap_create_alloc_class_buckets(heap, c) != 0)
				goto error_bucket_create;
		}
	}

	h->default_bucket = bucket_new(container_new_ctree(heap),
		alloc_class_by_id(h->alloc_classes, DEFAULT_ALLOC_CLASS_ID));

	if (h->default_bucket == NULL)
		goto error_bucket_create;

	heap_populate_buckets(heap);

	return 0;

error_bucket_create:
	for (unsigned i = 0; i < h->ncaches; ++i)
		bucket_group_destroy(h->caches[i].buckets);

	return -1;
}
Ejemplo n.º 3
0
int htable_add(htable* ht, void* key, size_t keylen, void* data, size_t dlen) { // {{{

	if (htable_load_factor(ht) > LOAD_FACTOR)
		htable_grow(ht);

	int hval;

	bucket** b = htable_find_pbucket(ht, key, keylen, &hval);

	if (*b)
		return HTABLE_NOT_FOUND;

	*b = bucket_new(key, keylen, data, dlen, hval);

	ht->entries++;

	return HTABLE_FOUND;
} // }}}
Ejemplo n.º 4
0
void htable_set(htable* ht, void* key, size_t keylen, void* data, size_t dlen) { // {{{

	if (htable_load_factor(ht) > LOAD_FACTOR)
		htable_grow(ht);

	int hval;
	bucket** b = htable_find_pbucket(ht, key, keylen, &hval);

	if (*b) {
		free(b[0]->data);
		b[0]->data = xmemdup(data, dlen);
		b[0]->dlen = dlen;
	} else {

		*b = bucket_new(key, keylen, data, dlen, hval);

		ht->entries++;
	}

} // }}}
Ejemplo n.º 5
0
/*
 * heap_create_alloc_class_buckets -- (internal) allocates all cache bucket
 * instances of the specified type
 */
static int
heap_create_alloc_class_buckets(struct palloc_heap *heap, struct alloc_class *c)
{
	struct heap_rt *h = heap->rt;
	int i;
	for (i = 0; i < (int)h->ncaches; ++i) {
		h->caches[i].buckets[c->id] = bucket_new(
			container_new_seglists(heap), c);
		if (h->caches[i].buckets[c->id] == NULL)
			goto error_cache_bucket_new;
	}

	return 0;

error_cache_bucket_new:
	for (i -= 1; i >= 0; --i) {
		bucket_delete(h->caches[i].buckets[c->id]);
	}

	return -1;
}
Ejemplo n.º 6
0
void dict_set(dict* d, char* key, void* item) {

  int index = hash(key, d->size);
  struct bucket* b = d->buckets[index];
  struct bucket** p = &d->buckets[index];
  
  while(true) {
    
    if (b == NULL) {
      *p = bucket_new(key, item);
      return;
    }
    
    if( strcmp(b->key, key) == 0) {
      b->item = item;
      return;
    }
    
    p = &b->next;
    b = b->next;
  }
  
}
Ejemplo n.º 7
0
int test_file(FILE *fp, int argc, char **argv) {
    char buf[65535 + 1];
    char *pos;
    unsigned int strategy = 0;  /* what bucketing strategy we're 
                                          using */
    void *ptr = NULL;
    unsigned int bucketsize = 0;
    struct params params = {0};
    struct chash *hash = NULL;
    char name[256];

    if (!parse_params(argc, argv, &params)) {
        fprintf(stderr, "failed to parse params\n");
        return 0;
    }

    while (fgets((char *) buf, 65535, fp)) {
        str_rtrim(buf);
        pos = (char *) str_ltrim(buf);

        if (!str_casecmp(pos, "new")) {

            /* creating a new bucket */
            unsigned int size = -1;

            if (ptr) {
                chash_delete(hash);
                free(ptr);
            }

            /* read parameters */
            if ((fscanf(fp, "%255s %u %u", name, &strategy, &size) == 3)
              && (size <= 65535) 
              && (bucketsize = size)
              && (ptr = malloc(size))
              && (hash = chash_ptr_new(1, 2.0, 
                /* some fn pointer casting dodginess */
                (unsigned int (*)(const void *)) str_len, 
                (int (*)(const void *, const void *)) str_cmp))
              && (bucket_new(ptr, bucketsize, strategy))) {
                /* succeeded, do nothing */
                if (params.verbose) {
                    printf("%s: new bucket with size %u strategy %u\n", name, 
                      size, strategy);
                }
            } else {
                fprintf(stderr, "%s: failed to create bucket\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "add")) {
            /* adding a term to the bucket */
            void *ret;
            unsigned int veclen,
                         succeed,
                         len;
            int toobig;

            if (!ptr) { return 0; }

            /* read parameters */
            if ((fscanf(fp, "%65535s %u %u", buf, &veclen, &succeed) == 3) 
              && (veclen <= 65535)) {

                len = str_len(buf);
                if ((((ret = bucket_alloc(ptr, bucketsize, strategy, buf, len, 
                        veclen, &toobig, NULL))
                      && succeed)
                    || (!ret && !succeed))) {
                    /* do nothing */
                    if (params.verbose) {
                        printf("%s: added term '%s'\n", name, buf);
                    }
                } else if (succeed) {
                    fprintf(stderr, "%s: failed to add '%s' to bucket\n", 
                      name, buf);
                    return 0;
                } else if (!succeed) {
                    fprintf(stderr, "%s: add '%s' succeeded but shouldn't "
                      "have\n", name, buf);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to add\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "ls")) {
            /* matching stuff in the bucket */
            unsigned int numterms,
                         i,
                         len,
                         veclen,
                         veclen2,
                         state;
            void *addr;
            struct chash *tmphash;
            const char *term;
            void **tmpptr,
                  *tmp;

            if (!ptr) { return 0; }

            if (!(tmphash = chash_ptr_new(1, 2.0, 
              /* some fn pointer casting dodginess */
              (unsigned int (*)(const void *)) str_len, 
              (int (*)(const void *, const void *)) str_cmp))) {
                fprintf(stderr, "%s: failed to init hashtable\n", name);
                return 0;
            }

            /* first, fill hashtable with all terms from bucket */
            state = 0;
            while ((term 
              = bucket_next_term(ptr, bucketsize, strategy,
                  &state, &len, &addr, &veclen))) {

                if (!((term = str_ndup(term, len)) 
                  && (chash_ptr_ptr_insert(tmphash, term, (void*) term) 
                      == CHASH_OK))) {

                    fprintf(stderr, "%s: failed to init hashtable\n", name);
                    return 0;
                }
            }

            /* now, take terms from file, comparing them with hashtable 
             * entries */
            if (fscanf(fp, "%u", &numterms)) {
                for (i = 0; i < numterms; i++) {
                    if (fscanf(fp, "%65535s %u ", buf, &veclen)) {
                        if (params.verbose) {
                            printf("%s: ls checking %s\n", name, buf);
                        }
                        
                        if ((addr = bucket_find(ptr, bucketsize, strategy,
                            buf, str_len(buf), &veclen2, NULL))
                          /* remove it from hashtable */
                          && chash_ptr_ptr_find(tmphash, buf, &tmpptr) 
                            == CHASH_OK
                          && chash_ptr_ptr_remove(tmphash, *tmpptr, &tmp) 
                            == CHASH_OK
                          && (free(tmp), 1)
                          && (veclen <= 65535)
                          && (veclen2 == veclen)
                          && fread(buf, veclen, 1, fp)
                          && ((buf[veclen] = '\0'), 1)
                          && (!params.verbose 
                            || printf("%s: ls check read '%s'\n", name, buf))
                          && !memcmp(buf, addr, veclen)) {
                            /* do nothing */
                        } else {
                            unsigned int j;

                            fprintf(stderr, "%s: ls failed cmp '%s' with '", 
                              name, buf);
                            for (j = 0; j < veclen; j++) {
                                putc(((char *) addr)[j], stderr);
                            }
                            fprintf(stderr, "'\n");
                            return 0;
                        }
                    } else {
                        fprintf(stderr, "%s: ls failed\n", name);
                        return 0;
                    }
                }

                if (chash_size(tmphash)) {
                    fprintf(stderr, "%s: ls failed\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: ls failed\n", name);
                return 0;
            }

            chash_delete(tmphash);

            if (params.verbose) {
                printf("%s: matched all (%u) entries\n", name, numterms);
            }
        } else if (!str_casecmp(pos, "set")) {
            /* setting the vector for a term in the bucket */
            unsigned int veclen,
                        reallen;
            void *addr;

            if (!ptr) { return 0; }

            /* read parameters */
            if ((fscanf(fp, "%65535s %u ", buf, &veclen) == 2) 
              && (veclen <= 65535)) {

                addr = bucket_find(ptr, bucketsize, strategy, buf, 
                  str_len(buf), &reallen, NULL);

                if (addr && (reallen == veclen) 
                  && fread(addr, 1, veclen, fp)) {
                    /* do nothing */
                    if (params.verbose) {
                        unsigned int j;

                        printf("%s: set term '%s' to '", name, buf);
                        for (j = 0; j < reallen; j++) {
                            putc(((char *) addr)[j], stdout);
                        }
                        printf("'\n");
                    }
                } else {
                    fprintf(stderr, "%s: failed to set!\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to set\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "realloc")) {
            /* reallocating a term in the bucket */
            unsigned int veclen,
                         succeed;
            int toobig;

            if (!ptr) { return 0; }

            /* read parameters */
            if ((fscanf(fp, "%65535s %u %u", buf, &veclen, &succeed) == 3) 
              && (veclen <= 65535)) {

                if (!bucket_realloc(ptr, bucketsize, strategy, buf, 
                  str_len(buf), veclen, &toobig)) {
                    fprintf(stderr, "%s: failed to realloc!\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to realloc\n", name);
                return 0;
            }

            if (params.verbose) {
                printf("%s: realloc'd term '%s'\n", name, buf);
            }
        } else if (!str_casecmp(pos, "rm")) {
            /* removing something from the bucket */
            unsigned int succeed;

            if (!ptr) { return 0; }

            if (fscanf(fp, "%65535s %u", buf, &succeed) == 2) {
                if (succeed) {

                    if (!(bucket_remove(ptr, bucketsize, strategy, buf, 
                      str_len(buf)))) {
                        fprintf(stderr, "%s: failed to rm '%s'\n", name, 
                          buf);
                        return 0;
                    } else if (params.verbose) {
                        printf("%s: rm term '%s'\n", name, buf);
                    }
                } else if (succeed) {
                    fprintf(stderr, "%s: failed to rm\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to rm\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "print")) {
            /* printing out the bucket contents */
            unsigned int state = 0,
                         len,
                         veclen;
            const char *term;
            char format[100];
            void *addr;

            if (!ptr) { 
                printf("can't print, no bucket\n");
            } else {
                do {
                    term 
                      = bucket_next_term(ptr, bucketsize, strategy, &state, 
                        &len, &addr, &veclen);
                } while (term 
                  && memcpy(buf, term, len)
                  && ((buf[len] = '\0') || 1)
                  && snprintf(format, 100, "%%.%us (%%u): '%%.%us' (%%u) "
                    "(off %%u)\n", len, veclen) 
                  && printf(format, term, len, (char*) addr, veclen, 
                    ((char *) addr) - (char *) ptr));

                if (!state) {
                    printf("(empty)\n");
                }

                printf("%u entries, %u data, %u string, %u overhead, %u free\n", 
                  bucket_entries(ptr, bucketsize, strategy), 
                  bucket_utilised(ptr, bucketsize, strategy), 
                  bucket_string(ptr, bucketsize, strategy), 
                  bucket_overhead(ptr, bucketsize, strategy),
                  bucket_unused(ptr, bucketsize, strategy));
            }
        } else if (!str_casecmp(pos, "match")) {
            unsigned int veclen,
                         veclen2;
            void *addr;

            if (fscanf(fp, "%65535s %u ", buf, &veclen)) {
                if ((addr = bucket_find(ptr, bucketsize, strategy,
                    buf, str_len(buf), &veclen2, NULL))
                  && (veclen <= 65535)
                  && (veclen2 >= veclen)
                  && (!params.verbose 
                    || printf("%s: match on '%s' ", name, buf))
                  && fread(buf, veclen, 1, fp)
                  && !memcmp(buf, addr, veclen)) {
                    if (params.verbose) {
                        printf("content succeeded\n");
                    }
                } else {
                    fprintf(stderr, "%s: match failed (%s vs %s)\n", name, buf,
                      (char *) addr);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: match failed\n", name);
                return 0;
            }
        } else if ((*pos != '#') && str_len(pos)) {
            fprintf(stderr, "%s: unknown command '%s'\n", name, pos);
            return 0;
        }
    }

    if (ptr) {
        chash_delete(hash);
        free(ptr);
    }

    return 1;
}
Ejemplo n.º 8
0
int buckets_accept_bucket(client_t *client, hash_t mask, hash_t hashmask)
{
	int accepted = -1;
	
	assert(client);
	assert(mask > 0);
	
	if (_bucket_transfer) {
		//  we are currently transferring another bucket, therefore we cannot accept another one.
		logger(LOG_WARN, "cant accept bucket, already transferring one.");
		accepted = 0;
	}
	else { 
		assert(_bucket_transfer == NULL);
		if (mask != _mask) {
			// the masks are different, we cannot accept a bucket unless our masks match... which should 
			// balance out once hashmasks have proceeded through all the nodes.
			logger(LOG_WARN, "cant accept bucket, masks are not compatible.");
			accepted = 0;
		}
		else {
			// now we need to check that this bucket isn't already handled by this server.

			assert(hashmask <= mask);
			assert(_mask == mask);
			
			// if we dont currently have a buckets list, we need to create one.
			if (_buckets == NULL) {
				_buckets = calloc(_mask + 1, sizeof(bucket_t *));
				assert(_buckets);
				assert(_buckets[0] == NULL);
				assert(_primary_buckets == 0);
				assert(_secondary_buckets == 0);
			}
			
			assert(_buckets);
			if (_buckets[hashmask]) {
				logger(LOG_ERROR, "cant accept bucket, already have that bucket.");
				accepted = 0;
			}
			else {
				logger(LOG_INFO, "accepting bucket. (%#llx/%#llx)", mask, hashmask);
				
				// need to create the bucket, and mark it as in-transit.
				bucket_t *bucket = bucket_new(hashmask);
				assert(bucket);
				_buckets[hashmask] = bucket;
				assert(data_in_transit() == 0);
				assert(bucket->transfer_client == NULL);
				assert(client->node);
				logger(LOG_DEBUG, "Setting transfer client ('%s') to bucket %#llx.", node_name(client->node), bucket->hashmask);
				bucket->transfer_client = client;
				assert(bucket->level < 0);
				accepted = 1;
				
				assert(_bucket_transfer == NULL);
				_bucket_transfer = bucket;
			}
		}
	}

	assert(accepted == 0 || accepted == 1);
	return(accepted);
}
Ejemplo n.º 9
0
// this function will take the current array, and put it aside, creating a new array based on the 
// new mask supplied (we can only make the mask bigger, and cannot shrink it).
// We create a new array, and for each entry, we compare it against the old mask, and use 
// the data for that hash from the old list.
// NOTE: We may be starting off with an empty lists.  If this is the first time we've 
//       received some hashmasks.  To implement this easily, if we dont already have hashmasks, we 
//       may need to create one that has a dummy entry in it.
void buckets_split_mask(hash_t current_mask, hash_t new_mask) 
{
	bucket_t **newbuckets = NULL;
	bucket_t **oldbuckets = NULL;
	
	int i;
	int index;
	
	assert(new_mask > current_mask);
	
	logger(LOG_INFO, "Splitting Mask: Old Mask: %#llx, New Mask; %#llx", current_mask, new_mask);
	
	// grab a copy of the existing buckets as the 'oldbuckets';
	oldbuckets = _buckets;
	_buckets = NULL;
	
	// make an appropriate sized new buckets list;
	newbuckets = malloc(sizeof(bucket_t *) * (new_mask+1));
	assert(newbuckets);
	
	// go through every hash for this mask.
	for (i=0; i<=new_mask; i++) {

		// determine what the old index is.
		index = i & current_mask;
		
		// create the new bucket ONLY if we already have a bucket object for that index.
		if (oldbuckets == NULL || oldbuckets[index] == NULL) {
			newbuckets[i] = NULL;
		}
		else {
			// we have a bucket for this old index.  So we need to create a new one for this index.
			
			
			newbuckets[i] = bucket_new(i);

			assert(newbuckets[i]->data);
			assert(newbuckets[i]->data->next == NULL);
			assert(oldbuckets[index]->data);
			assert(oldbuckets[index]->data->ref > 0);
			newbuckets[i]->data->next = oldbuckets[index]->data;
			oldbuckets[index]->data->ref ++;

			assert(newbuckets[i]->hashmask == i);
			newbuckets[i]->level = oldbuckets[index]->level;
			
			newbuckets[i]->source_node = oldbuckets[index]->source_node;
			newbuckets[i]->backup_node = oldbuckets[index]->backup_node;
			newbuckets[i]->logging_node = oldbuckets[index]->logging_node;
			
			newbuckets[i]->primary_node = oldbuckets[index]->primary_node;
			newbuckets[i]->secondary_node = oldbuckets[index]->secondary_node;
			
			assert(data_in_transit() == 0);
		}
	}

	assert(_mask >= 0);
	assert(new_mask > _mask);
	_mask = new_mask;
	
	// clean up the old buckets list.
	if (oldbuckets) {
		for (i=0; i<=_mask; i++) {
			if (oldbuckets[i]) {
				assert(oldbuckets[i]->data);
				assert(oldbuckets[i]->data->ref > 1);
				oldbuckets[i]->data->ref --;
				assert(oldbuckets[i]->data->ref > 0);
				
				oldbuckets[i]->data = NULL;
				
				bucket_close(oldbuckets[i]);
			}
		}
	}	
	
	_buckets = newbuckets;
	assert(_buckets);
}
Ejemplo n.º 10
0
/*
 * heap_buckets_init -- (internal) initializes bucket instances
 */
static int
heap_buckets_init(PMEMobjpool *pop)
{
	struct pmalloc_heap *h = pop->heap;
	int i;

	//printf("calling heap_buckets_init \n");
	bucket_proto[0].unit_max = RUN_UNIT_MAX;

	/*
	 * To take use of every single bit available in the run the unit size
	 * would have to be calculated using following expression:
	 * (RUNSIZE / (MAX_BITMAP_VALUES * BITS_PER_VALUE)), but to preserve
	 * cacheline alignment a little bit of memory at the end of the run
	 * is left unused.
	 */
	bucket_proto[0].unit_size = MIN_RUN_SIZE;

	for (i = 1; i < MAX_BUCKETS - 1; ++i) {
		bucket_proto[i].unit_max = RUN_UNIT_MAX;
		bucket_proto[i].unit_size =
				bucket_proto[i - 1].unit_size *
				bucket_proto[i - 1].unit_max;
	}

	bucket_proto[i].unit_max = -1;
	bucket_proto[i].unit_size = CHUNKSIZE;

	h->last_run_max_size = bucket_proto[i - 1].unit_size *
				(bucket_proto[i - 1].unit_max - 1);

	h->bucket_map = Malloc(sizeof (*h->bucket_map) * h->last_run_max_size);
	if (h->bucket_map == NULL)
		goto error_bucket_map_malloc;

	for (i = 0; i < MAX_BUCKETS; ++i) {
		h->buckets[i] = bucket_new(bucket_proto[i].unit_size,
					bucket_proto[i].unit_max);
		if (h->buckets[i] == NULL)
			goto error_bucket_new;
	}

	/* XXX better way to fill the bucket map */
	for (i = 0; i < h->last_run_max_size; ++i) {
		for (int j = 0; j < MAX_BUCKETS - 1; ++j) {
			/*
			 * Skip the last unit, so that the distribution
			 * of buckets in the map is better.
			 */
			if ((bucket_proto[j].unit_size *
				((bucket_proto[j].unit_max - 1))) >= i) {
				h->bucket_map[i] = h->buckets[j];
				break;
			}
		}
	}

	heap_populate_buckets(pop);

	return 0;

error_bucket_new:
	Free(h->bucket_map);

	for (i = i - 1; i >= 0; --i)
		bucket_delete(h->buckets[i]);
error_bucket_map_malloc:

	return ENOMEM;
}