static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp, MprSymbolTable *table, const char *key) { MprSymbol *sp, *prev; int index, rc; mprAssert(key); index = hashIndex(key, table->hashSize); if (bucketIndex) { *bucketIndex = index; } sp = table->buckets[index]; prev = 0; while (sp) { rc = strcmp(sp->key, key); if (rc == 0) { if (prevSp) { *prevSp = prev; } return sp; } prev = sp; mprAssert(sp != sp->next); sp = sp->next; } return 0; }
entry *findName(char lastname[], entry *pHead) { unsigned int idx = hashIndex(lastname); pHead = hash_p[idx]; while (pHead != NULL) { if (strcasecmp(lastname, pHead->lastName) == 0) return pHead; pHead = pHead->pNext; } return NULL; }
int symDelete(sym_fd_t sd, char_t *name) { sym_tabent_t *tp; sym_t *sp, *last; char_t *cp; int hindex; a_assert(name && *name); a_assert(0 <= sd && sd < symMax); tp = sym[sd]; a_assert(tp); /* * Calculate the first daisy-chain from the hash table. If non-zero, then * we have daisy-chain, so scan it and look for the symbol. */ last = NULL; hindex = hashIndex(tp, name); if ((sp = tp->hash_table[hindex]) != NULL) { for ( ; sp; sp = sp->forw) { cp = sp->name.value.string; if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { break; } last = sp; } } if (sp == (sym_t*) NULL) { /* Not Found */ return -1; } /* * Unlink and free the symbol. Last will be set if the element to be deleted * is not first in the chain. */ if (last) { last->forw = sp->forw; } else { tp->hash_table[hindex] = sp->forw; } valueFree(&sp->name); valueFree(&sp->content); bfree(B_L, (void*) sp); return 0; }
int findElementHash(Key *key, Hash *hash) { int index; Node *h; index = hashIndex(key, hash->size); h = hash->table[index]; while( h!=NULL && !equalKey(&h->key,key) ) h = h->next; if( h==NULL ) return 0; return h->count; }
int setElementHash(Key *key, Hash *hash, int count) { int index; Node *h,*p=NULL; index = hashIndex(key, hash->size); if( hash->table[index]==NULL ) { if( (h = (Node*) mymalloc(sizeof(Node)))==NULL ) { fprintf(stderr, "Cannot allocate memory for new entry in hash table"); exit(2); } hash->table[index] = h; hash->total++; keyCopy(&(h->key),key); h->count = count; h->next = NULL; return count; } h = hash->table[index]; //assert(h); while( h!=NULL && !equalKey(&h->key, key)) { p = h; h = h->next; } if(h == NULL) { if( (h = (Node*) mymalloc(sizeof(Node)))==NULL ) { fprintf(stderr, "Cannot allocate memory for new entry in hash table"); exit(2); } hash->total++; //assert(p); p->next = h; keyCopy(&(h->key),key); h->count = count; h->next = NULL; return count; } h->count = count; return h->count; }
entry *append(char lastName[], entry *not_used) { unsigned int idx; entry *e = NULL; entry **head = NULL; // calc hash index idx = hashIndex(lastName); head = &hash_p[idx]; // link on the head on hash_p[index] e = (entry *) malloc(sizeof(entry)); strcpy(e->lastName, lastName); if (*head == 0) { e->pNext = NULL; } else { e->pNext = *head; } *head = e; return e; }
const Status Index::startScan(const void* scanValue) { int hashvalue; curValue = scanValue; // read in and pin down the bucket containing entries with 'value' // in the buffer pool Status status = hashIndex(curValue, hashvalue); if (status != OK) return status; int pageNo = curPageNo = headerPage->dir[hashvalue]; status = bufMgr->readPage(file, pageNo, (Page*&)curBuc); if (status != OK) return status; curOffset = 0; return OK; }
const Status Index::deleteEntry(const void* value, const RID & rid) { Status status; int index; Bucket* bucket; status = hashIndex(value, index); // read in the bucket that might have the entry in it int pageNo = headerPage->dir[index]; status = bufMgr->readPage(file, pageNo, (Page*&)bucket); if (status != OK) return status; // scan the bucket for the entry. Delete it if found for(int i = 0; i < bucket->slotCnt; i++) { status = matchRec(bucket, value, i); if (status == OK) { if (!memcmp(&rid, &(bucket->data[i*recSize + headerPage->length]), sizeof(RID))) { // the entry is found. Decrease the entry counts in the bucket // and copy the last entry in the bucket to the slot occupied // by the deleted entry (bucket->slotCnt)--; memcpy(&(bucket->data[i*recSize]), &(bucket->data[recSize*(bucket->slotCnt)]),recSize); status = bufMgr->unPinPage(file, pageNo, true); return status; } } } status = bufMgr->unPinPage(file, pageNo, false); if (status != OK) return status; return RECNOTFOUND; }
static sym_t *hash(sym_tabent_t *tp, char_t *name) { a_assert(tp); return tp->hash_table[hashIndex(tp, name)]; }
sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg) { sym_tabent_t *tp; sym_t *sp, *last; char_t *cp; int hindex; a_assert(name); a_assert(0 <= sd && sd < symMax); tp = sym[sd]; a_assert(tp); /* * Calculate the first daisy-chain from the hash table. If non-zero, then * we have daisy-chain, so scan it and look for the symbol. */ last = NULL; hindex = hashIndex(tp, name); if ((sp = tp->hash_table[hindex]) != NULL) { for (; sp; sp = sp->forw) { cp = sp->name.value.string; if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { break; } last = sp; } if (sp) { /* * Found, so update the value * If the caller stores handles which require freeing, they * will be lost here. It is the callers responsibility to free * resources before overwriting existing contents. We will here * free allocated strings which occur due to value_instring(). * We should consider providing the cleanup function on the open rather * than the close and then we could call it here and solve the problem. */ if (sp->content.valid) { valueFree(&sp->content); } sp->content = v; sp->arg = arg; return sp; } /* * Not found so allocate and append to the daisy-chain */ sp = (sym_t*) balloc(B_L, sizeof(sym_t)); if (sp == NULL) { return NULL; } sp->name = valueString(name, VALUE_ALLOCATE); sp->content = v; sp->forw = (sym_t*) NULL; sp->arg = arg; last->forw = sp; } else { /* * Daisy chain is empty so we need to start the chain */ sp = (sym_t*) balloc(B_L, sizeof(sym_t)); if (sp == NULL) { return NULL; } tp->hash_table[hindex] = sp; tp->hash_table[hashIndex(tp, name)] = sp; sp->forw = (sym_t*) NULL; sp->content = v; sp->arg = arg; sp->name = valueString(name, VALUE_ALLOCATE); } return sp; }
const Status Index::insertEntry(const void *value, RID rid) { Bucket* bucket; Status status; Bucket *newBucket; int newPageNo; char data[PAGESIZE*2]; int counter; int index; // If the 'unique' flag is set, scan the index to see if the // <attribute, rid> pair already exists if (headerPage->unique == UNIQUE) { RID outRid; if((status = startScan(value)) != OK) return status; while ((status = scanNext(outRid)) != NOMORERECS) { if (status != OK) return status; if (!memcmp(&outRid, &rid, sizeof(RID))) return NONUNIQUEENTRY; } if((status = endScan()) != OK) return status; } // Get the bucket containing the entry into buffer pool status = hashIndex(value, index); int pageNo = headerPage->dir[index]; #ifdef DEBUGIND cout << "Inserting entry " << *(int*)value << " to bucket " << pageNo << endl; #endif status = bufMgr->readPage(file, pageNo, (Page*&)bucket); if (status != OK) return status; // the bucket needs to be splitted if the number of entries // on the bucket equals the maximum if (bucket->slotCnt == numSlots) { // splitting bucket // allocate a new bucket status = bufMgr->allocPage(file, newPageNo, (Page*&)newBucket); if (status != OK) return status; // Initialize this newly allocated bucket newBucket->depth = ++(bucket->depth); newBucket->slotCnt = 0; // Copy all (value, rid) pairs in the old bucket and the new // entry to a temporary area memcpy(data, bucket->data, numSlots*recSize); memcpy(&(data[numSlots*recSize]), value, headerPage->length); memcpy(&(data[numSlots*recSize + headerPage->length]), &rid, sizeof(RID)); counter = bucket->slotCnt + 1; bucket->slotCnt = 0; // the directory needs to be doubled if the depth of the bucket // being splitted equals the depth of the directory if (bucket->depth > headerPage->depth) { // doubling directory // The directory is doubled and the lower half of the directory // is copied to the upper half int newDirSize = 2 * dirSize; if (newDirSize > DIRSIZE) return DIROVERFLOW; for (int i = 0; i < dirSize; i++) headerPage->dir[i + dirSize] = headerPage->dir[i]; dirSize = newDirSize; (headerPage->depth)++; headerPage->dir[index + (1 << (bucket->depth - 1))] = newPageNo; } else { // reset the appropriate directories to the new bucket int oldindex = index % (1 << (bucket->depth - 1)); int newindex = oldindex + (1 << (bucket->depth - 1)); for (int j = 0; j < dirSize; j++) if ((j % (1 << (bucket->depth))) == newindex) headerPage->dir[j] = newPageNo; } #ifdef DEBUGIND printDir(); #endif // call insertEntry recursively to insert all (value, rid) // pairs in the temporary area to the index for (int k = 0; k < counter; k++) { value = &(data[k * recSize]); rid = * ((RID *)((char *)value + headerPage->length)); status = insertEntry(value, rid); if (status != OK) return status; } status = bufMgr->unPinPage(file, newPageNo, true); if (status != OK) return status; } else { // There is sufficient free space in the bucket. Insert (value, rid) here int offset = (bucket->slotCnt) * recSize; memcpy(&(bucket->data[offset]), value, headerPage->length); memcpy(&(bucket->data[offset+headerPage->length]), &rid, sizeof(RID)); (bucket->slotCnt)++; } status = bufMgr->unPinPage(file, pageNo, true); return status; }