예제 #1
0
파일: buckets.hpp 프로젝트: ANCL/autopilot
    inline void hash_buckets<A, G>::delete_buckets()
    {      
        bucket_ptr end = this->get_bucket(this->bucket_count_);

        for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
            clear_bucket(begin);
        }

        // Destroy the buckets (including the sentinel bucket).
        ++end;
        for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
            bucket_alloc().destroy(begin);
        }

        bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1);

        this->buckets_ = bucket_ptr();
    }
예제 #2
0
파일: buckets.hpp 프로젝트: ANCL/autopilot
    inline void hash_buckets<A, G>::create_buckets()
    {
        // The array constructor will clean up in the event of an
        // exception.
        allocator_array_constructor<bucket_allocator>
            constructor(bucket_alloc());

        // Creates an extra bucket to act as a sentinel.
        constructor.construct(bucket(), this->bucket_count_ + 1);

        // Set up the sentinel (node_ptr cast)
        bucket_ptr sentinel = constructor.get() +
            static_cast<std::ptrdiff_t>(this->bucket_count_);
        sentinel->next_ = sentinel;

        // Only release the buckets once everything is successfully
        // done.
        this->buckets_ = constructor.release();
    }
static void
create_data(struct group_desc_list *group_desc_list) {
  struct group_desc *group_desc;
  struct bucket *bucket;
  struct action *action;
  struct ofp_action_output *action_output;
  uint16_t length = 0xe0;
  int i;
  int j;
  int k;

  TAILQ_INIT(group_desc_list);
  for (i = 0; i < group_desc_num; i++) {
    group_desc = group_desc_alloc(length);
    group_desc->ofp.length = length;
    group_desc->ofp.type = OFPGT_SELECT;
    group_desc->ofp.group_id = (uint32_t) (0x01 + i);

    TAILQ_INIT(&group_desc->bucket_list);
    for (j = 0; j < bucket_num; j++) {
      bucket = bucket_alloc();
      bucket->ofp.len = 0x30;
      bucket->ofp.weight = (uint16_t) (0x02 + j);
      bucket->ofp.watch_port = (uint32_t) (0x03 +j);
      bucket->ofp.watch_group = (uint32_t) (0x4 + j);

      TAILQ_INIT(&bucket->action_list);
      for (k = 0; k < action_num; k++) {
        action = action_alloc(0x10);
        action->ofpat.type = OFPAT_OUTPUT;
        action->ofpat.len = 0x10;
        action_output = (struct ofp_action_output *) &action->ofpat;
        action_output->port = (uint32_t) (0x05 + k);
        action_output->max_len = (uint16_t) (0x06 + k);
        TAILQ_INSERT_TAIL(&bucket->action_list, action, entry);
      }
      TAILQ_INSERT_TAIL(&group_desc->bucket_list, bucket, entry);
    }
    TAILQ_INSERT_TAIL(group_desc_list, group_desc, entry);
  }
}
예제 #4
0
/*
 * hash_search -- look up key in table and perform action
 *
 * action is one of HASH_FIND/HASH_ENTER/HASH_REMOVE
 *
 * RETURNS: NULL if table is corrupted, a pointer to the element
 * 	found/removed/entered if applicable, TRUE otherwise.
 *	foundPtr is TRUE if we found an element in the table 
 *	(FALSE if we entered one).
 */
long *
hash_search(HTAB *hashp,
	    char *keyPtr, 
	    HASHACTION action,	/*
				 * HASH_FIND / HASH_ENTER / HASH_REMOVE
				 * HASH_FIND_SAVE / HASH_REMOVE_SAVED
				 */
	    bool *foundPtr)
{
    uint32 bucket;
    long segment_num;
    long segment_ndx;
    SEGMENT segp;
    register ELEMENT *curr;
    HHDR	*hctl;
    BUCKET_INDEX	currIndex;
    BUCKET_INDEX	*prevIndexPtr;
    char *		destAddr;
    static struct State {
	ELEMENT      *currElem;
	BUCKET_INDEX currIndex;
	BUCKET_INDEX *prevIndex;
    } saveState;
    
    Assert((hashp && keyPtr));
    Assert((action == HASH_FIND) || (action == HASH_REMOVE) || (action == HASH_ENTER) || (action == HASH_FIND_SAVE) || (action == HASH_REMOVE_SAVED));
    
    hctl = hashp->hctl;
    
# if HASH_STATISTICS
    hash_accesses++;
    hashp->hctl->accesses++;
# endif
    if (action == HASH_REMOVE_SAVED)
	{
	    curr = saveState.currElem;
	    currIndex = saveState.currIndex;
	    prevIndexPtr = saveState.prevIndex;
	    /*
	     * Try to catch subsequent errors
	     */
	    Assert(saveState.currElem && !(saveState.currElem = 0));
	}
    else
	{
	    bucket = call_hash(hashp, keyPtr, hctl->keysize);
	    segment_num = bucket >> hctl->sshift;
	    segment_ndx = bucket & ( hctl->ssize - 1 );
	    
	    segp = GET_SEG(hashp,segment_num);
	    
	    Assert(segp);
	    
	    prevIndexPtr = &segp[segment_ndx];
	    currIndex = *prevIndexPtr;
	    /*
	     * Follow collision chain
	     */
	    for (curr = NULL;currIndex != INVALID_INDEX;) {
		/* coerce bucket index into a pointer */
		curr = GET_BUCKET(hashp,currIndex);
		
		if (! memcmp((char *)&(curr->key), keyPtr, hctl->keysize)) {
		    break;
		} 
		prevIndexPtr = &(curr->next);
		currIndex = *prevIndexPtr;
# if HASH_STATISTICS
		hash_collisions++;
		hashp->hctl->collisions++;
# endif
	    }
	}
    
    /*
     *  if we found an entry or if we weren't trying
     * to insert, we're done now.
     */
    *foundPtr = (bool) (currIndex != INVALID_INDEX);
    switch (action) {
    case HASH_ENTER:
	if (currIndex != INVALID_INDEX)
	    return(&(curr->key));
	break;
    case HASH_REMOVE:
    case HASH_REMOVE_SAVED:
	if (currIndex != INVALID_INDEX) {
	    Assert(hctl->nkeys > 0);
	    hctl->nkeys--;
	    
	    /* add the bucket to the freelist for this table.  */
	    *prevIndexPtr = curr->next;
	    curr->next = hctl->freeBucketIndex;
	    hctl->freeBucketIndex = currIndex;
	    
	    /* better hope the caller is synchronizing access to
	     * this element, because someone else is going to reuse
	     * it the next time something is added to the table
	     */
	    return (&(curr->key));
	}
	return((long *) TRUE);
    case HASH_FIND:
	if (currIndex != INVALID_INDEX)
	    return(&(curr->key));
	return((long *)TRUE);
    case HASH_FIND_SAVE:
	if (currIndex != INVALID_INDEX)
	    {
		saveState.currElem = curr;
		saveState.prevIndex = prevIndexPtr;
		saveState.currIndex = currIndex;
		return(&(curr->key));
	    }
	return((long *)TRUE);
    default:
	/* can't get here */
	return (NULL);
    }
    
    /* 
      If we got here, then we didn't find the element and
      we have to insert it into the hash table
      */
    Assert(currIndex == INVALID_INDEX);
    
    /* get the next free bucket */
    currIndex = hctl->freeBucketIndex;
    if (currIndex == INVALID_INDEX) {
	
	/* no free elements.  allocate another chunk of buckets */
	if (! bucket_alloc(hashp)) {
	    return(NULL);
	}
	currIndex = hctl->freeBucketIndex;
    }
    Assert(currIndex != INVALID_INDEX);
    
    curr = GET_BUCKET(hashp,currIndex);
    hctl->freeBucketIndex = curr->next;
    
    /* link into chain */
    *prevIndexPtr = currIndex;	
    
    /* copy key and data */
    destAddr = (char *) &(curr->key);
    memmove(destAddr,keyPtr,hctl->keysize);
    curr->next = INVALID_INDEX;
    
    /* let the caller initialize the data field after 
     * hash_search returns.
     */
    /*	memmove(destAddr,keyPtr,hctl->keysize+hctl->datasize);*/
    
    /*
     * Check if it is time to split the segment
     */
    if (++hctl->nkeys / (hctl->max_bucket+1) > hctl->ffactor) {
	/*
	  fprintf(stderr,"expanding on '%s'\n",keyPtr);
	  hash_stats("expanded table",hashp);
	  */
	if (! expand_table(hashp))
	    return(NULL);
    }
    return (&(curr->key));
}
예제 #5
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;
}