mooncached.lua

Sun, 01 Aug 2010 01:23:32 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Sun, 01 Aug 2010 01:23:32 +0100
changeset 11
85c18da60925
parent 9
ff6a712c26c8
child 12
fb941ed514c6
permissions
-rw-r--r--

Fix README header

local server = require "net.server";
local log = require "util.logger".init("memcached");
local memcache = require "util.memcache";

local cache = memcache.new();

local memcached_listener = {};
local command_handlers = {};

--- Network handlers

function memcached_listener.onconnect(conn)
end

function memcached_listener.onincoming(conn, line)
	local command, params_pos = line:match("^(%S+) ?()");
	local command_handler = command_handlers[command];
	if command_handler then
		local ok, err = command_handler(conn, line:sub(params_pos));
		if ok == false then
			conn:write("CLIENT_ERROR "..err.."\r\n");
		end
	elseif command then
		log("warn", "Client sent unknown command: %s", command);
		conn:write("ERROR\r\n");
	end
end

function memcached_listener.ondisconnect(conn, err)
end

--- Command handlers

function command_handlers.set(conn, params)
	local key, flags, exptime, bytes, reply = params:match("(%S+) (%d+) (%d+) (%d+) ?(.*)$");
	flags, exptime, bytes, reply = tonumber(flags), tonumber(exptime), tonumber(bytes), reply ~= "noreply";
	if not (flags and exptime and bytes) then
		return false, "Invalid parameter(s)";
	end
	conn:set_mode("*a");
	local received_count, received_buffer = 0, {};
	local function handle_data(conn, data)
		log("debug", "Received data of length "..#data.." out of "..bytes);
		received_count = received_count + #data;
		received_buffer[#received_buffer+1] = data;
		if received_count >= bytes then
			received_buffer = table.concat(received_buffer);
			local ok, err = cache:set(key, flags, exptime, received_buffer:sub(1,bytes));
			if ok then
				conn:send("STORED\r\n");
			else
				conn:send("SERVER_ERROR "..(err or "Unknown error").."\r\n");
			end
			conn:setlistener(memcached_listener);
			conn:set_mode("*l");
			if received_count > bytes then
				log("debug", "Re-handling %d extra bytes", received_count-bytes);
				memcached_listener.onincoming(conn, received_buffer:sub(bytes+1));
			end
		end
	end
	conn:setlistener({
		onincoming = handle_data;
		ondisconnect = memcached_listener.ondisconnect;
	});
	log("debug", "Waiting for "..bytes.." bytes from client");
	return true;
end

function command_handlers.get(conn, keys)
	for key in keys:gmatch("%S+") do
		local flags, data = cache:get(key);
		if flags then
			conn:write("VALUE "..key.." "..flags.." "..#data.."\r\n"..data.."\r\n");
		end
	end
	conn:write("END\r\n");
	return true;
end

function command_handlers.version(conn)
	conn:write("VERSION Mooncached 0.1\r\n");
	return true;
end

function command_handlers.quit(conn)
	conn:close();
	return true;
end

logger.setwriter(function (name, level, format, ...) return print(name, level, format:format(...)); end);

server.addserver("*", 11211, memcached_listener, "*l");

server.loop();

mercurial