Merge 0.10->trunk
[prosody.git] / util / cache.lua
index d3639b3f7aebc791bfdf8b57d395af810b03e25e..44bbfe3098427ae9c9fef7ba9b6ce8d9a4830ddf 100644 (file)
@@ -51,10 +51,13 @@ function cache_methods:set(k, v)
                return true;
        end
        -- Check whether we need to remove oldest k/v
-       local on_evict, evicted_key, evicted_value;
        if self._count == self.size then
                local tail = self._tail;
-               on_evict, evicted_key, evicted_value = self._on_evict, tail.key, tail.value;
+               local on_evict, evicted_key, evicted_value = self._on_evict, tail.key, tail.value;
+               if on_evict ~= nil and (on_evict == false or on_evict(evicted_key, evicted_value) == false) then
+                       -- Cache is full, and we're not allowed to evict
+                       return false;
+               end
                _remove(self, tail);
                self._data[evicted_key] = nil;
        end
@@ -62,9 +65,6 @@ function cache_methods:set(k, v)
        m = { key = k, value = v, prev = nil, next = nil };
        self._data[k] = m;
        _insert(self, m);
-       if on_evict and evicted_key then
-               on_evict(evicted_key, evicted_value, self);
-       end
        return true;
 end
 
@@ -88,10 +88,56 @@ function cache_methods:items()
        end
 end
 
+function cache_methods:values()
+       local m = self._head;
+       return function ()
+               if not m then
+                       return;
+               end
+               local v = m.value;
+               m = m.next;
+               return v;
+       end
+end
+
 function cache_methods:count()
        return self._count;
 end
 
+function cache_methods:head()
+       local head = self._head;
+       if not head then return nil, nil; end
+       return head.key, head.value;
+end
+
+function cache_methods:tail()
+       local tail = self._tail;
+       if not tail then return nil, nil; end
+       return tail.key, tail.value;
+end
+
+function cache_methods:table()
+       if not self.proxy_table then
+               self.proxy_table = setmetatable({}, {
+                       __index = function (t, k)
+                               return self:get(k);
+                       end;
+                       __newindex = function (t, k, v)
+                               if not self:set(k, v) then
+                                       error("failed to insert key into cache - full");
+                               end
+                       end;
+                       __pairs = function (t)
+                               return self:items();
+                       end;
+                       __len = function (t)
+                               return self:count();
+                       end;
+               });
+       end
+       return self.proxy_table;
+end
+
 local function new(size, on_evict)
        size = assert(tonumber(size), "cache size must be a number");
        size = math.floor(size);