# HG changeset patch # User shinysky # Date 1280385401 -28800 # Node ID 95d4d53f09a103a9ff08f64dbeed80f5b70922ed # Parent 96e29ff5fa07bf3cb60f75dcfee622256fc6c263 mod_archive: keep collections in REVERSE chronological order(not tested). diff -r 96e29ff5fa07 -r 95d4d53f09a1 mod_archive/mod_archive.lua --- a/mod_archive/mod_archive.lua Mon Jul 26 21:15:41 2010 +0800 +++ b/mod_archive/mod_archive.lua Thu Jul 29 14:36:41 2010 +0800 @@ -38,9 +38,12 @@ dm.store(node, host, PREFS_DIR, st.preserialize(data)); end -local function os_time() - -- return tostring(os.time(os.date('!*t'))); - return datetime.datetime(); +local function os_date() + return os.date("!*t"); +end + +local function date_time(t) + return datetime.datetime(t); end local function date_parse(s) @@ -48,46 +51,88 @@ return os.time({year=year, month=month, day=day, hour=hour, min=min, sec=sec}); end +-- local function list_push(node, host, collection) +-- local data = dm.list_load(node, host, ARCHIVE_DIR); +-- if data then +-- table.insert(data, collection, 1); +-- dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); +-- else +-- dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(collection)); +-- end +-- end + +local function list_insert(node, host, collection) + local data = dm.list_load(node, host, ARCHIVE_DIR); + if data then + local s, e = 1, #data; + while true do + local c = st.deserialize(data[s]); + if collection.attr["start"] >= c.attr["start"] then + table.insert(data, collection, s); + break; + end + c = st.deserialize(data[e]); + if collection.attr["start"] <= c.attr["start"] then + table.insert(data, collection, e+1); + break; + end + local m = math.floor((s + e) / 2); + c = st.deserialize(data[m]); + if collection.attr["start"] > c.attr["start"] then + e = m - 1; + elseif collection.attr["start"] < c.attr["start"] then + s = m + 1; + else + table.insert(data, collection, m); + break; + end + end + dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); + else + dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(collection)); + end +end + local function store_msg(msg, node, host, isfrom) local body = msg:child_with_name("body"); local thread = msg:child_with_name("thread"); local data = dm.list_load(node, host, ARCHIVE_DIR); - local tag = (isfrom and "from") or "to"; - local utc = os_time(); + local tag = isfrom and "from" or "to"; + local with = isfrom and msg.attr.to or msg.attr.from; + local utc = os_date(); + local utc_secs = os.time(utc); + local utc_datetime = date_time(utc); if data then - if thread then - for k, v in ipairs(data) do - local collection = st.deserialize(v); - if collection.attr["thread"] == thread:get_text() then - -- TODO figure out secs - collection:tag(tag, {secs='1', utc=utc}):add_child(body); - local ver = tonumber(collection.attr["version"]) + 1; - collection.attr["version"] = tostring(ver); - collection.attr["access"] = utc; - data[k] = collection; - dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); - return; + -- TODO assuming the collection list are in REVERSE chronological order + for k, v in ipairs(data) do + local collection = st.deserialize(v); + if thread and collection.attr["thread"] == thread:get_text() + or + not thread + and collection.attr["with"] == with + and os.difftime(utc_secs, date_parse(collection.attr["start"])) < 14400 then + local dt = 1; + for i = #collection, 1, -1 do + local s = collection[i].attr["utc_secs"]; + if s then + dt = os.difftime(utc_secs, tonumber(s)); + break; + end end - end - else -- if the last collection occurs on the same day, then join it - -- TODO assuming the collection list are in chronological order - local collection = st.deserialize(data[#data]); - local difftime = os.difftime(date_parse(utc), date_parse(collection.attr["start"])); - if difftime < 86400 then -- 60 * 60 * 24 - collection:tag(tag, {secs='1', utc=utc}):add_child(body); + collection:tag(tag, {secs=dt, utc_secs=utc_secs}):add_child(body); local ver = tonumber(collection.attr["version"]) + 1; collection.attr["version"] = tostring(ver); - collection.attr["access"] = utc; - data[#data] = collection; + collection.attr["access"] = utc_datetime; + data[k] = collection; dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); return; end end end -- not found, create new collection - local collection = st.stanza('chat', {with = isfrom and msg.attr.to or msg.attr.from, start=utc, thread=thread:get_text(), version='0', access=utc}); - collection:tag(tag, {secs='0', utc=utc}):add_child(body); - dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(collection)); + local collection = st.stanza('chat', {with=with, start=utc_datetime, thread=thread and thread:get_text() or nil, version='0', access=utc_datetime}); + collection:tag(tag, {secs='0', utc_secs=utc_secs}):add_child(body); + list_insert(node, host, collection); end local function save_result(collection) @@ -157,7 +202,6 @@ elseif elem.name == "item" then local found = false; for child in data:children() do - -- TODO bare JID or full JID? if child.name == elem.name and child.attr["jid"] == elem.attr["jid"] then for k, v in pairs(elem.attr) do child.attr[k] = v; @@ -341,7 +385,7 @@ local ver = tonumber(collection.attr["version"]) + 1; collection.attr["version"] = tostring(ver); collection.attr["subject"] = elem.attr["subject"]; - collection.attr["access"] = os_time(); + collection.attr["access"] = date_time(); origin.send(st.reply(stanza):add_child(save_result(collection))); data[k] = collection; dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); @@ -351,10 +395,10 @@ end -- not found, create new collection elem.attr["version"] = "0"; - elem.attr["access"] = os_time(); + elem.attr["access"] = date_time(); origin.send(st.reply(stanza):add_child(save_result(elem))); -- TODO check if elem is valid(?) - dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(elem)); + list_insert(node, host, elem); -- TODO unsuccessful reply return true; end @@ -556,7 +600,7 @@ if res then -- table.remove(data, i); local temp = st.stanza('chat', collection.attr); - temp.attr["access"] = os_time(); + temp.attr["access"] = date_time(); data[i] = temp; found = true; end