typename ChHashTable<T>::DataNode ChHashTable<T>::make_node(const T& Data) { try { // if we have an allocator, use it if(allocator) { DataNode mem = reinterpret_cast<ChHTNode*>(allocator->Allocate()); DataNode node = new (mem) ChHTNode(Data); return node; } // no allocator, just use new DataNode node = new ChHTNode(Data); return node; } // catach exception from new, throw our own catch (std::bad_alloc &ba) { throw(HashTableException(HashTableException::E_NO_MEMORY, "No memory is available")); } }
const ValueType &remove(const KeyType &key) { auto record = get_record(key); if (record == nullptr) { throw HashTableException(); } if (record->head == nullptr) { hashTable_[get_hash_index(key)] = record->tail; } else if (record->tail == nullptr) { record->head->tail = nullptr; } else { record->head->tail = record->tail; record->tail->head = record->head; } size_--; const ValueType &value = record->value; delete record; return value; }
const ValueType &get(const KeyType &key) const { auto record = get_record(key); if (record == nullptr) { throw HashTableException(); } return record->value; }
void ChHashTable<T>::insert(const char *Key, const T& Data) { try { if( ((stats.Count_ + 1) / static_cast<double>(stats.TableSize_)) > config.MaxLoadFactor_) grow_table(); // place in hash table where this will be inserted unsigned index = config.HashFunc_(Key, stats.TableSize_); HeadNode head = &table[index]; // get head of the list of keys DataNode list = head->Nodes; // increment probe counter for initally finding place // in hash table ++stats.Probes_; // check list for duplicate while(list) { // increment probe counter ++stats.Probes_; // found a duplicate, throw exception if(strncmp(Key, list->Key, MAX_KEYLEN) == 0) throw (HashTableException(HashTableException::E_DUPLICATE, "Item being inserted is a duplicate")); // move to next node list = list->Next; } // duplicate was not found, start inserting // make the node DataNode insert_node = make_node(Data); strncpy(insert_node->Key, Key, MAX_KEYLEN); // insert at the front of the list at the correct index insert_node->Next = head->Nodes; head->Nodes = insert_node; // increment item counter ++stats.Count_; // increment counter for list at table[index] ++head->Count; } // catch ecept from make_node call catch (HashTableException &exception) { // throw it back to client throw exception; } }
void ChHashTable<T>::grow_table() { try { // record old table size to move nodes to new one unsigned old_table_size = stats.TableSize_; // calculate new table size double factor = std::ceil(stats.TableSize_ * config.GrowthFactor_); unsigned new_table_size = GetClosestPrime(static_cast<unsigned>(factor)); stats.TableSize_ = new_table_size; // make the new table HeadNode new_table = new ChHTHeadNode[stats.TableSize_]; //start moving nodes for(unsigned i = 0; i < old_table_size; ++i) { DataNode list = table[i].Nodes; // move keys from this list to new table while(list) { DataNode temp = list->Next; // get updated index from new table size unsigned index = stats.HashFunc_(list->Key, stats.TableSize_); // hook up this node to the new table list->Next = new_table[index].Nodes; new_table[index].Nodes = list; // move to the next node list = temp; } // go to next list of keys } // delete the old table and connect the new one delete [] table; table = new_table; ++stats.Expansions_; } catch (std::bad_alloc &ba) { throw(HashTableException(HashTableException::E_NO_MEMORY, "No memory is available")); } }
void BufHashTbl::insert(const File* file, const PageId pageNo, const FrameId frameNo) { int index = hash(file, pageNo); hashBucket* tmpBuc = ht[index]; while (tmpBuc) { if (tmpBuc->file == file && tmpBuc->pageNo == pageNo) throw HashAlreadyPresentException(tmpBuc->file->filename(), tmpBuc->pageNo, tmpBuc->frameNo); tmpBuc = tmpBuc->next; } tmpBuc = new hashBucket; if (!tmpBuc) throw HashTableException(); tmpBuc->file = (File*) file; tmpBuc->pageNo = pageNo; tmpBuc->frameNo = frameNo; tmpBuc->next = ht[index]; ht[index] = tmpBuc; }
const T& ChHashTable<T>::find(const char *Key) const { // find where requested key would be unsigned index = stats.HashFunc_(Key, stats.TableSize_); DataNode list = table[index].Nodes; // walk list of keys looking for requested key while(list) { // increment probe counter ++stats.Probes_; // found our key, return the Data if(strncmp(Key, list->Key, MAX_KEYLEN) == 0) return list->Data; // move to next key list = list->Next; } // didnt find key requested, throw exception throw(HashTableException(HashTableException::E_ITEM_NOT_FOUND, "Item requested to be found does not exist")); }