提供基本的ttl测试用例
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

255 行
6.5 KiB

  1. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. #if defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_ANDROID)
  5. #include <unordered_set>
  6. #elif defined(LEVELDB_PLATFORM_OSX)
  7. #include <ext/hash_set>
  8. #elif defined(LEVELDB_PLATFORM_CHROMIUM)
  9. #include "base/hash_tables.h"
  10. #else
  11. #include <hash_set> // TODO(sanjay): Switch to unordered_set when possible.
  12. #endif
  13. #include <assert.h>
  14. #include "leveldb/cache.h"
  15. #include "port/port.h"
  16. #include "util/hash.h"
  17. #include "util/mutexlock.h"
  18. namespace leveldb {
  19. Cache::~Cache() {
  20. }
  21. namespace {
  22. // LRU cache implementation
  23. // An entry is a variable length heap-allocated structure. Entries
  24. // are kept in a circular doubly linked list ordered by access time.
  25. struct LRUHandle {
  26. void* value;
  27. void (*deleter)(const Slice&, void* value);
  28. LRUHandle* next;
  29. LRUHandle* prev;
  30. size_t charge; // TODO(opt): Only allow uint32_t?
  31. size_t key_length;
  32. size_t refs; // TODO(opt): Pack with "key_length"?
  33. char key_data[1]; // Beginning of key
  34. Slice key() const {
  35. // For cheaper lookups, we allow a temporary Handle object
  36. // to store a pointer to a key in "value".
  37. if (next == this) {
  38. return *(reinterpret_cast<Slice*>(value));
  39. } else {
  40. return Slice(key_data, key_length);
  41. }
  42. }
  43. };
  44. // Pick a platform specific hash_set instantiation
  45. #if defined(LEVELDB_PLATFORM_CHROMIUM) && defined(OS_WIN)
  46. // Microsoft's hash_set deviates from the standard. See
  47. // http://msdn.microsoft.com/en-us/library/1t4xas78(v=vs.80).aspx
  48. // for details. Basically the 2 param () operator is a less than and
  49. // the 1 param () operator is a hash function.
  50. struct HandleHashCompare : public stdext::hash_compare<LRUHandle*> {
  51. size_t operator() (LRUHandle* h) const {
  52. Slice k = h->key();
  53. return Hash(k.data(), k.size(), 0);
  54. }
  55. bool operator() (LRUHandle* a, LRUHandle* b) const {
  56. return a->key().compare(b->key()) < 0;
  57. }
  58. };
  59. typedef base::hash_set<LRUHandle*, HandleHashCompare> HandleTable;
  60. #else
  61. struct HandleHash {
  62. inline size_t operator()(LRUHandle* h) const {
  63. Slice k = h->key();
  64. return Hash(k.data(), k.size(), 0);
  65. }
  66. };
  67. struct HandleEq {
  68. inline bool operator()(LRUHandle* a, LRUHandle* b) const {
  69. return a->key() == b->key();
  70. }
  71. };
  72. # if defined(LEVELDB_PLATFORM_CHROMIUM)
  73. typedef base::hash_set<LRUHandle*, HandleHash, HandleEq> HandleTable;
  74. # elif defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_ANDROID)
  75. typedef std::unordered_set<LRUHandle*, HandleHash, HandleEq> HandleTable;
  76. # else
  77. typedef __gnu_cxx::hash_set<LRUHandle*, HandleHash, HandleEq> HandleTable;
  78. # endif
  79. #endif
  80. class LRUCache : public Cache {
  81. public:
  82. explicit LRUCache(size_t capacity);
  83. virtual ~LRUCache();
  84. virtual Handle* Insert(const Slice& key, void* value, size_t charge,
  85. void (*deleter)(const Slice& key, void* value));
  86. virtual Handle* Lookup(const Slice& key);
  87. virtual void Release(Handle* handle);
  88. virtual void* Value(Handle* handle);
  89. virtual void Erase(const Slice& key);
  90. virtual uint64_t NewId();
  91. private:
  92. void LRU_Remove(LRUHandle* e);
  93. void LRU_Append(LRUHandle* e);
  94. void Unref(LRUHandle* e);
  95. // Constructor parameters
  96. const size_t capacity_;
  97. // mutex_ protects the following state.
  98. port::Mutex mutex_;
  99. size_t usage_;
  100. uint64_t last_id_;
  101. // Dummy head of LRU list.
  102. // lru.prev is newest entry, lru.next is oldest entry.
  103. LRUHandle lru_;
  104. HandleTable table_;
  105. };
  106. LRUCache::LRUCache(size_t capacity)
  107. : capacity_(capacity),
  108. usage_(0),
  109. last_id_(0) {
  110. // Make empty circular linked list
  111. lru_.next = &lru_;
  112. lru_.prev = &lru_;
  113. }
  114. LRUCache::~LRUCache() {
  115. table_.clear();
  116. for (LRUHandle* e = lru_.next; e != &lru_; ) {
  117. LRUHandle* next = e->next;
  118. assert(e->refs == 1); // Error if caller has an unreleased handle
  119. Unref(e);
  120. e = next;
  121. }
  122. }
  123. void LRUCache::Unref(LRUHandle* e) {
  124. assert(e->refs > 0);
  125. e->refs--;
  126. if (e->refs <= 0) {
  127. usage_ -= e->charge;
  128. (*e->deleter)(e->key(), e->value);
  129. free(e);
  130. }
  131. }
  132. void LRUCache::LRU_Remove(LRUHandle* e) {
  133. e->next->prev = e->prev;
  134. e->prev->next = e->next;
  135. }
  136. void LRUCache::LRU_Append(LRUHandle* e) {
  137. // Make "e" newest entry by inserting just before lru_
  138. e->next = &lru_;
  139. e->prev = lru_.prev;
  140. e->prev->next = e;
  141. e->next->prev = e;
  142. }
  143. Cache::Handle* LRUCache::Lookup(const Slice& key) {
  144. MutexLock l(&mutex_);
  145. LRUHandle dummy;
  146. dummy.next = &dummy;
  147. dummy.value = const_cast<Slice*>(&key);
  148. HandleTable::iterator iter = table_.find(&dummy);
  149. if (iter == table_.end()) {
  150. return NULL;
  151. } else {
  152. LRUHandle* e = const_cast<LRUHandle*>(*iter);
  153. e->refs++;
  154. LRU_Remove(e);
  155. LRU_Append(e);
  156. return reinterpret_cast<Handle*>(e);
  157. }
  158. }
  159. void* LRUCache::Value(Handle* handle) {
  160. return reinterpret_cast<LRUHandle*>(handle)->value;
  161. }
  162. void LRUCache::Release(Handle* handle) {
  163. MutexLock l(&mutex_);
  164. Unref(reinterpret_cast<LRUHandle*>(handle));
  165. }
  166. Cache::Handle* LRUCache::Insert(const Slice& key, void* value, size_t charge,
  167. void (*deleter)(const Slice& key, void* value)) {
  168. MutexLock l(&mutex_);
  169. LRUHandle* e = reinterpret_cast<LRUHandle*>(
  170. malloc(sizeof(LRUHandle)-1 + key.size()));
  171. e->value = value;
  172. e->deleter = deleter;
  173. e->charge = charge;
  174. e->key_length = key.size();
  175. e->refs = 2; // One from LRUCache, one for the returned handle
  176. memcpy(e->key_data, key.data(), key.size());
  177. LRU_Append(e);
  178. usage_ += charge;
  179. std::pair<HandleTable::iterator,bool> p = table_.insert(e);
  180. if (!p.second) {
  181. // Kill existing entry
  182. LRUHandle* old = const_cast<LRUHandle*>(*(p.first));
  183. LRU_Remove(old);
  184. table_.erase(p.first);
  185. table_.insert(e);
  186. Unref(old);
  187. }
  188. while (usage_ > capacity_ && lru_.next != &lru_) {
  189. LRUHandle* old = lru_.next;
  190. LRU_Remove(old);
  191. table_.erase(old);
  192. Unref(old);
  193. }
  194. return reinterpret_cast<Handle*>(e);
  195. }
  196. void LRUCache::Erase(const Slice& key) {
  197. MutexLock l(&mutex_);
  198. LRUHandle dummy;
  199. dummy.next = &dummy;
  200. dummy.value = const_cast<Slice*>(&key);
  201. HandleTable::iterator iter = table_.find(&dummy);
  202. if (iter != table_.end()) {
  203. LRUHandle* e = const_cast<LRUHandle*>(*iter);
  204. LRU_Remove(e);
  205. table_.erase(iter);
  206. Unref(e);
  207. }
  208. }
  209. uint64_t LRUCache::NewId() {
  210. MutexLock l(&mutex_);
  211. return ++(last_id_);
  212. }
  213. } // end anonymous namespace
  214. Cache* NewLRUCache(size_t capacity) {
  215. return new LRUCache(capacity);
  216. }
  217. }