diff --git a/src/HashMap.h b/src/HashMap.h new file mode 100644 index 0000000000000000000000000000000000000000..dae8012b958f71591de9b4ce3367c7d47bdca275 --- /dev/null +++ b/src/HashMap.h @@ -0,0 +1,150 @@ +#pragma once + +/** + * Copyright 2017 HashMap Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "HashNode.h" +#include <cstddef> +#include "Key.h" +#include "Buffer.h" +#define TABLE_SIZE 50000 + +namespace RAMCloud +{ + class HashMap + { + public: + HashMap() : table() + {} + + ~HashMap() + { + // destroy all buckets one by one + for (size_t i = 0; i < TABLE_SIZE; ++i) + { + HashNode *entry = table[i]; + + while (entry != NULL) + { + HashNode *prev = entry; + entry = entry->getNext(); + delete prev; + } + + table[i] = NULL; + } + } + + bool get(Key &key, Buffer &value) + { + unsigned long hashValue = hashFunc(key); + // HashNode *entry = table[hashValue]; + HashNode *entry = table[hashValue]; + + while (entry != NULL) + { + if (entry->getKey() == key) + { + void **ptr; + entry->getValue().peek(0,ptr); + value.appendCopy(*ptr, entry->getValue().size()); // verify if should be dereferenced + return true; + } + + entry = entry->getNext(); + } + + return false; + } + + void put(Key &key, const Buffer &value) + { + unsigned long hashValue = hashFunc(key); + HashNode *prev = NULL; + HashNode *entry = table[hashValue]; + + while (entry != NULL && entry->getKey() != key) + { + prev = entry; + entry = entry->getNext(); + } + + if (entry == NULL) + { + entry = new HashNode(key, value); + + if (prev == NULL) + { + // insert as first bucket + table[hashValue] = entry; + } + else + { + prev->setNext(entry); + } + } + else + { + // just update the value + entry->setValue(value); + } + } + + void remove(Key &key) + { + unsigned long hashValue = hashFunc(key); + HashNode *prev = NULL; + HashNode *entry = table[hashValue]; + + while (entry != NULL && entry->getKey() != key) + { + prev = entry; + entry = entry->getNext(); + } + + if (entry == NULL) + { + // key not found + return; + } + else + { + if (prev == NULL) + { + // remove first bucket of the list + table[hashValue] = entry->getNext(); + } + else + { + prev->setNext(entry->getNext()); + } + + delete entry; + } + } + + private: + HashMap(const HashMap &other); + const HashMap &operator=(const HashMap &other); + // hash table + HashNode *table[TABLE_SIZE]; + unsigned long hashFunc(Key &k) const + { + return k.getHash(); + } + }; + +} diff --git a/src/HashNode.h b/src/HashNode.h new file mode 100644 index 0000000000000000000000000000000000000000..dbd8262bf7652ec147a076148b528ecfdf8b537c --- /dev/null +++ b/src/HashNode.h @@ -0,0 +1,84 @@ +#pragma once + +/** + * Copyright 2017 HashMap Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <cstddef> +#include "Key.h" +#include "Buffer.h" + +namespace RAMCloud +{ + // Hash node class template + // template <typename Key, typename Buffer> + class HashNode + { + private: + // key-value pair + // next bucket with the same key + public: + Key _key; + Buffer _value; + HashNode *_next; + // disallow copy and assignment + HashNode(const HashNode &); + HashNode &operator=(const HashNode &); + HashNode(const Key &key, Buffer &value) : + _key( + key.getTableId(), + key.getStringKey(), + key.getStringKeyLength() + ), + _value(), + _next(NULL) + { + void **ptr; + value.peek(0,ptr); + _value.appendCopy(*ptr, value.size()); + } + + Key getKey() const + { + return _key; + } + + Buffer getValue() const + { + return _value; + } + + void setValue(Buffer& value) + { + void **ptr; + value.peek(0, ptr); + _value.appendCopy(*ptr, value.size()); + // _value = value; + } + + HashNode *getNext() const + { + return _next; + } + + void setNext(HashNode *next) + { + _next = next; + } + + + }; + +} diff --git a/src/ObjectManager.cc b/src/ObjectManager.cc index 6089ae0ab52585d30c41c460cfe7bd504077eaf3..c6011e0c50872ce58f5c33dbdfa9f634a53aa051 100644 --- a/src/ObjectManager.cc +++ b/src/ObjectManager.cc @@ -34,6 +34,7 @@ #include "WallTime.h" #include "MasterService.h" #include <emmintrin.h> // _mm_clflush and _mm_mfence +#include "HashMap.h" namespace RAMCloud { diff --git a/src/ObjectManager.h b/src/ObjectManager.h index d1ccb2914fe7057e88e44343d4f32f2232614c6f..fec745da5578ce090d2e81ee22ecd16506d4a073 100644 --- a/src/ObjectManager.h +++ b/src/ObjectManager.h @@ -38,6 +38,7 @@ #include "MasterTableMetadata.h" #include "UnackedRpcResults.h" #include "LockTable.h" +#include "HashMap.h" namespace RAMCloud { @@ -416,6 +417,14 @@ class ObjectManager : public LogEntryHandlers, */ int tombstoneProtectorCount; + + /** + * This hash table maps the key to a pointer to the value in DRAM. + * + */ + HashMap cacheTable; + + friend class CleanerCompactionBenchmark; friend class ObjectManagerBenchmark;