mod_storage_xmlarchive/mod_storage_xmlarchive.lua
changeset 1973 e63dba236a2a
parent 1835 004d3bfc05ea
child 2042 a85b5c3791dc
equal deleted inserted replaced
1972:95ad6e68e203 1973:e63dba236a2a
    10 local st = require"util.stanza";
    10 local st = require"util.stanza";
    11 local dt = require"util.datetime";
    11 local dt = require"util.datetime";
    12 local new_stream = require "util.xmppstream".new;
    12 local new_stream = require "util.xmppstream".new;
    13 local empty = {};
    13 local empty = {};
    14 
    14 
    15 local function fallocate(f, offset, len)
       
    16 	-- This assumes that current position == offset
       
    17 	local fake_data = (" "):rep(len);
       
    18 	local ok, msg = f:write(fake_data);
       
    19 	if not ok then
       
    20 		return ok, msg;
       
    21 	end
       
    22 	return f:seek("set", offset);
       
    23 end;
       
    24 
       
    25 pcall(function()
       
    26 	local pposix = require "util.pposix";
       
    27 	fallocate = pposix.fallocate or fallocate;
       
    28 end);
       
    29 
       
    30 local archive = {};
    15 local archive = {};
    31 local archive_mt = { __index = archive };
    16 local archive_mt = { __index = archive };
    32 
    17 
    33 function archive:append(username, _, data, when, with)
    18 function archive:append(username, _, data, when, with)
    34 	if type(when) ~= "number" then
    19 	if type(when) ~= "number" then
    41 
    26 
    42 	username = username or "@";
    27 	username = username or "@";
    43 	data = tostring(data) .. "\n";
    28 	data = tostring(data) .. "\n";
    44 
    29 
    45 	local day = dt.date(when);
    30 	local day = dt.date(when);
    46 	local filename = dm.getpath(username.."@"..day, module.host, self.store, "xml", true);
    31 	local ok, err = dm.append_raw(username.."@"..day, module.host, self.store, "xml", data);
    47 
    32 	if not ok then
    48 	local ok, err;
    33 		return nil, err;
    49 	local f = io.open(filename, "r+");
    34 	end
    50 	if not f then
    35 
    51 		f, err = io.open(filename, "w");     if not f then return nil, err; end
    36 	local offset = ok and err;
    52 		ok, err = dm.list_append(username, module.host, self.store, day);
       
    53 		if not ok then return nil, err; end
       
    54 	end
       
    55 
       
    56 	local offset = f:seek("end"); -- Seek to the end and collect current file length
       
    57 	-- then make sure there is enough free space for what we're about to add
       
    58 	ok, err = fallocate(f, offset, #data); if not ok then return nil, err; end
       
    59 	ok, err = f:write(data);               if not ok then return nil, err; end
       
    60 	ok, err = f:close();                   if not ok then return nil, err; end
       
    61 
    37 
    62 	local id = day .. "-" .. hmac_sha256(username.."@"..day.."+"..offset, data, true):sub(-16);
    38 	local id = day .. "-" .. hmac_sha256(username.."@"..day.."+"..offset, data, true):sub(-16);
    63 	ok, err = dm.list_append(username.."@"..day, module.host, self.store, { id = id, when = dt.datetime(when), with = with, offset = offset, length = #data });
    39 	ok, err = dm.list_append(username.."@"..day, module.host, self.store, { id = id, when = dt.datetime(when), with = with, offset = offset, length = #data });
    64 	if not ok then return nil, err; end
    40 	if offset == 0 then
       
    41 		-- means the message is at the beginnig of the file, so it's a new day
       
    42 		-- so we add this new day to the "index"
       
    43 		dm.list_append(username, module.host, self.store, day);
       
    44 	end
       
    45 	if not ok then
       
    46 		return nil, err;
       
    47 	end
    65 	return id;
    48 	return id;
    66 end
    49 end
    67 
    50 
    68 function archive:find(username, query)
    51 function archive:find(username, query)
    69 	username = username or "@";
    52 	username = username or "@";