Changeset

6947:032313f356c9

Merge 0.10->trunk
author Matthew Wild <mwild1@gmail.com>
date Thu, 26 Nov 2015 00:19:31 +0000
parents 6936:2ca1d54d4b92 (current diff) 6946:31fb9eb9edce (diff)
children 6952:db085e55555f
files
diffstat 6 files changed, 300 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/mod_blocklist.lua	Wed Nov 25 15:34:54 2015 +0100
+++ b/plugins/mod_blocklist.lua	Thu Nov 26 00:19:31 2015 +0000
@@ -19,12 +19,13 @@
 local storage = module:open_store();
 local sessions = prosody.hosts[module.host].sessions;
 
--- Cache of blocklists used since module was loaded
-local cache = {};
-if module:get_option_boolean("blocklist_weak_cache") then
-	-- Lower memory usage, more IO and latency
-	setmetatable(cache, { __mode = "v" });
-end
+-- Cache of blocklists by username may randomly expire at any time
+local cache = setmetatable({}, { __mode = "v" });
+
+-- Second level of caching, keeps a fixed number of items,
+-- also anchors items in the above cache
+local cache_size = module:get_option_number("blocklist_cache_size", 64);
+local cache2 = require"util.cache".new(cache_size);
 
 local null_blocklist = {};
 
@@ -36,6 +37,7 @@
 		return ok, err;
 	end
 	-- Successful save, update the cache
+	cache2:set(username, blocklist);
 	cache[username] = blocklist;
 	return true;
 end
@@ -72,6 +74,9 @@
 local function get_blocklist(username)
 	local blocklist = cache[username];
 	if not blocklist then
+		blocklist = cache2:get(username);
+	end
+	if not blocklist then
 		if not user_exists(username, module.host) then
 			return null_blocklist;
 		end
@@ -79,8 +84,9 @@
 		if not blocklist then
 			blocklist = migrate_privacy_list(username);
 		end
-		cache[username] = blocklist;
+		cache2:set(username, blocklist);
 	end
+	cache[username] = blocklist;
 	return blocklist;
 end
 
--- a/tests/test.lua	Wed Nov 25 15:34:54 2015 +0100
+++ b/tests/test.lua	Thu Nov 26 00:19:31 2015 +0000
@@ -20,6 +20,7 @@
 	dotest "util.ip"
 	dotest "util.stanza"
 	dotest "util.sasl.scram"
+	dotest "util.cache"
 
 	dosingletest("test_sasl.lua", "latin1toutf8");
 	dosingletest("test_utf8.lua", "valid");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test_util_cache.lua	Thu Nov 26 00:19:31 2015 +0000
@@ -0,0 +1,174 @@
+
+function new(new)
+	local c = new(5);
+
+	assert_equal(c:count(), 0);
+	
+	c:set("one", 1)
+	assert_equal(c:count(), 1);
+	c:set("two", 2)
+	c:set("three", 3)
+	c:set("four", 4)
+	c:set("five", 5);
+	assert_equal(c:count(), 5);
+	
+	c:set("foo", nil);
+	assert_equal(c:count(), 5);
+	
+	assert_equal(c:get("one"), 1);
+	assert_equal(c:get("two"), 2);
+	assert_equal(c:get("three"), 3);
+	assert_equal(c:get("four"), 4);
+	assert_equal(c:get("five"), 5);
+
+	assert_equal(c:get("foo"), nil);
+	assert_equal(c:get("bar"), nil);
+	
+	c:set("six", 6);
+	assert_equal(c:count(), 5);
+	
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), 2);
+	assert_equal(c:get("three"), 3);
+	assert_equal(c:get("four"), 4);
+	assert_equal(c:get("five"), 5);
+	assert_equal(c:get("six"), 6);
+	
+	c:set("three", nil);
+	assert_equal(c:count(), 4);
+	
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), 2);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), 4);
+	assert_equal(c:get("five"), 5);
+	assert_equal(c:get("six"), 6);
+	
+	c:set("seven", 7);
+	assert_equal(c:count(), 5);
+	
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), 2);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), 4);
+	assert_equal(c:get("five"), 5);
+	assert_equal(c:get("six"), 6);
+	assert_equal(c:get("seven"), 7);
+	
+	c:set("eight", 8);
+	assert_equal(c:count(), 5);
+	
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), nil);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), 4);
+	assert_equal(c:get("five"), 5);
+	assert_equal(c:get("six"), 6);
+	assert_equal(c:get("seven"), 7);
+	assert_equal(c:get("eight"), 8);
+	
+	c:set("four", 4);
+	assert_equal(c:count(), 5);
+	
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), nil);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), 4);
+	assert_equal(c:get("five"), 5);
+	assert_equal(c:get("six"), 6);
+	assert_equal(c:get("seven"), 7);
+	assert_equal(c:get("eight"), 8);
+	
+	c:set("nine", 9);
+	assert_equal(c:count(), 5);
+	
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), nil);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), 4);
+	assert_equal(c:get("five"), nil);
+	assert_equal(c:get("six"), 6);
+	assert_equal(c:get("seven"), 7);
+	assert_equal(c:get("eight"), 8);
+	assert_equal(c:get("nine"), 9);
+
+	local keys = { "nine", "four", "eight", "seven", "six" };
+	local values = { 9, 4, 8, 7, 6 };
+	local i = 0;	
+	for k, v in c:items() do
+		i = i + 1;
+		assert_equal(k, keys[i]);
+		assert_equal(v, values[i]);
+	end
+	assert_equal(i, 5);
+	
+	c:set("four", "2+2");
+	assert_equal(c:count(), 5);
+
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), nil);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), "2+2");
+	assert_equal(c:get("five"), nil);
+	assert_equal(c:get("six"), 6);
+	assert_equal(c:get("seven"), 7);
+	assert_equal(c:get("eight"), 8);
+	assert_equal(c:get("nine"), 9);
+
+	local keys = { "four", "nine", "eight", "seven", "six" };
+	local values = { "2+2", 9, 8, 7, 6 };
+	local i = 0;	
+	for k, v in c:items() do
+		i = i + 1;
+		assert_equal(k, keys[i]);
+		assert_equal(v, values[i]);
+	end
+	assert_equal(i, 5);
+	
+	c:set("foo", nil);
+	assert_equal(c:count(), 5);
+
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), nil);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), "2+2");
+	assert_equal(c:get("five"), nil);
+	assert_equal(c:get("six"), 6);
+	assert_equal(c:get("seven"), 7);
+	assert_equal(c:get("eight"), 8);
+	assert_equal(c:get("nine"), 9);
+
+	local keys = { "four", "nine", "eight", "seven", "six" };
+	local values = { "2+2", 9, 8, 7, 6 };
+	local i = 0;	
+	for k, v in c:items() do
+		i = i + 1;
+		assert_equal(k, keys[i]);
+		assert_equal(v, values[i]);
+	end
+	assert_equal(i, 5);
+	
+	c:set("four", nil);
+	
+	assert_equal(c:get("one"), nil);
+	assert_equal(c:get("two"), nil);
+	assert_equal(c:get("three"), nil);
+	assert_equal(c:get("four"), nil);
+	assert_equal(c:get("five"), nil);
+	assert_equal(c:get("six"), 6);
+	assert_equal(c:get("seven"), 7);
+	assert_equal(c:get("eight"), 8);
+	assert_equal(c:get("nine"), 9);
+
+	local keys = { "nine", "eight", "seven", "six" };
+	local values = { 9, 8, 7, 6 };
+	local i = 0;	
+	for k, v in c:items() do
+		i = i + 1;
+		assert_equal(k, keys[i]);
+		assert_equal(v, values[i]);
+	end
+	assert_equal(i, 4);
+	
+
+end
--- a/util-src/pposix.c	Wed Nov 25 15:34:54 2015 +0100
+++ b/util-src/pposix.c	Thu Nov 26 00:19:31 2015 +0000
@@ -642,6 +642,10 @@
 	lua_setfield(L, -2, "version");
 	lua_pushstring(L, uname_info.machine);
 	lua_setfield(L, -2, "machine");
+#ifdef _GNU_SOURCE
+	lua_pushstring(L, uname_info.domainname);
+	lua_setfield(L, -2, "domainname");
+#endif
 	return 1;
 }
 
--- a/util/cache.lua	Wed Nov 25 15:34:54 2015 +0100
+++ b/util/cache.lua	Thu Nov 26 00:19:31 2015 +0000
@@ -1,11 +1,3 @@
-local cache_methods = {};
-local cache_mt = { __index = cache_methods };
-
-local function new(size)
-	assert(size > 0, "cache size must be greater than zero");
-	local data = {};
-	return setmetatable({ data = data, count = 0, size = size, head = nil, tail = nil }, cache_mt);
-end
 
 local function _remove(list, m)
 	if m.prev then
@@ -14,29 +6,32 @@
 	if m.next then
 		m.next.prev = m.prev;
 	end
-	if list.tail == m then
-		list.tail = m.prev;
+	if list._tail == m then
+		list._tail = m.prev;
 	end
-	if list.head == m then
-		list.head = m.next;
+	if list._head == m then
+		list._head = m.next;
 	end
-	list.count = list.count - 1;
+	list._count = list._count - 1;
 end
 
 local function _insert(list, m)
-	if list.head then
-		list.head.prev = m;
+	if list._head then
+		list._head.prev = m;
 	end
-	m.prev, m.next = nil, list.head;
-	list.head = m;
-	if not list.tail then
-		list.tail = m;
+	m.prev, m.next = nil, list._head;
+	list._head = m;
+	if not list._tail then
+		list._tail = m;
 	end
-	list.count = list.count + 1;
+	list._count = list._count + 1;
 end
 
+local cache_methods = {};
+local cache_mt = { __index = cache_methods };
+
 function cache_methods:set(k, v)
-	local m = self.data[k];
+	local m = self._data[k];
 	if m then
 		-- Key already exists
 		if v ~= nil then
@@ -47,27 +42,33 @@
 		else
 			-- Remove from list
 			_remove(self, m);
-			self.data[k] = nil;
+			self._data[k] = nil;
 		end
-		return;
+		return true;
 	end
 	-- New key
 	if v == nil then
-		return;
+		return true;
 	end
 	-- Check whether we need to remove oldest k/v
-	if self.count == self.size then
-		self.data[self.tail.key] = nil;
-		_remove(self, self.tail);
+	if self._count == self.size then
+		local tail = self._tail;
+		local on_evict = self._on_evict;
+		if on_evict then
+			on_evict(tail.key, tail.value);
+		end
+		_remove(self, tail);
+		self._data[tail.key] = nil;
 	end
 
 	m = { key = k, value = v, prev = nil, next = nil };
-	self.data[k] = m;
+	self._data[k] = m;
 	_insert(self, m);
+	return true;
 end
 
 function cache_methods:get(k)
-	local m = self.data[k];
+	local m = self._data[k];
 	if m then
 		return m.value;
 	end
@@ -75,7 +76,7 @@
 end
 
 function cache_methods:items()
-	local m = self.head;
+	local m = self._head;
 	return function ()
 		if not m then
 			return;
@@ -86,6 +87,18 @@
 	end
 end
 
+function cache_methods:count()
+	return self._count;
+end
+
+local function new(size, on_evict)
+	size = assert(tonumber(size), "cache size must be a number");
+	size = math.floor(size);
+	assert(size > 0, "cache size must be greater than zero");
+	local data = {};
+	return setmetatable({ _data = data, _count = 0, size = size, _head = nil, _tail = nil, _on_evict = on_evict }, cache_mt);
+end
+
 return {
 	new = new;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/session.lua	Thu Nov 26 00:19:31 2015 +0000
@@ -0,0 +1,65 @@
+local initialize_filters = require "util.filters".initialize;
+local logger = require "util.logger";
+
+local function new_session(typ)
+	local session = {
+		type = typ .. "_unauthed";
+	};
+	return session;
+end
+
+local function set_id(session)
+	local id = typ .. tostring(session):match("%x+$"):lower();
+	session.id = id;
+	return session;
+end
+
+local function set_logger(session)
+	local log = logger.init(id);
+	session.log = log;
+	return session;
+end
+
+local function set_conn(session, conn)
+	session.conn = conn;
+	session.ip = conn:ip();
+	return session;
+end
+
+local function set_send(session)
+	local conn = session.conn;
+	if not conn then
+		function session.send(data)
+			log("debug", "Discarding data sent to unconnected session: %s", tostring(data));
+			return false;
+		end
+		return session;
+	end
+	local filter = initialize_filters(session);
+	local w = conn.write;
+	session.send = function (t)
+		if t.name then
+			t = filter("stanzas/out", t);
+		end
+		if t then
+			t = filter("bytes/out", tostring(t));
+			if t then
+				local ret, err = w(conn, t);
+				if not ret then
+					session.log("debug", "Error writing to connection: %s", tostring(err));
+					return false, err;
+				end
+			end
+		end
+		return true;
+	end
+	return session;
+end
+
+return {
+	new = new_session;
+	set_id = set_id;
+	set_logger = set_logger;
+	set_conn = set_conn;
+	set_send = set_send;
+}