Software /
code /
prosody
Diff
util/datamanager.lua @ 8015:ecb110f45c92
Merge 0.10->trunk
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 28 Mar 2017 20:14:35 +0200 |
parent | 8014:ff3787033abb |
child | 8092:0a1c0f1107d2 |
line wrap: on
line diff
--- a/util/datamanager.lua Mon Mar 27 18:30:11 2017 +0200 +++ b/util/datamanager.lua Tue Mar 28 20:14:35 2017 +0200 @@ -17,7 +17,6 @@ local os_remove = os.remove; local os_rename = os.rename; local tonumber = tonumber; -local tostring = tostring; local next = next; local type = type; local t_insert = table.insert; @@ -31,21 +30,12 @@ local prosody = prosody; local raw_mkdir = lfs.mkdir; -local function fallocate(f, offset, len) - -- This assumes that current position == offset - local fake_data = (" "):rep(len); - local ok, msg = f:write(fake_data); - if not ok then - return ok, msg; - end - f:seek("set", offset); - return true; -end; +local atomic_append; local ENOENT = 2; pcall(function() local pposix = require "util.pposix"; raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask - fallocate = pposix.fallocate or fallocate; + atomic_append = pposix.atomic_append; ENOENT = pposix.ENOENT or ENOENT; end); @@ -65,6 +55,19 @@ end end +if not atomic_append then + function atomic_append(f, data) + local pos = f:seek(); + if not f:write(data) or not f:flush() then + f:seek("set", pos); + f:write((" "):rep(#data)); + f:flush(); + return nil, "write-failed"; + end + return true; + end +end + local _mkdir = {}; local function mkdir(path) path = path:gsub("/", path_separator); -- TODO as an optimization, do this during path creation rather than here @@ -220,26 +223,16 @@ if type(data) ~= "string" then return; end local filename = getpath(username, host, datastore, ext, true); - local ok; - local f, msg = io_open(filename, "r+"); + local f = io_open(filename, "r+"); if not f then return atomic_store(filename, data); -- File did probably not exist, let's create it end local pos = f:seek("end"); - ok, msg = fallocate(f, pos, #data); - if not ok then - log("warn", "fallocate() failed: %s", tostring(msg)); - -- This doesn't work on every file system - end - if f:seek() ~= pos then - log("debug", "fallocate() changed file position"); - f:seek("set", pos); - end + local ok, msg = atomic_append(f, data); - ok, msg = f:write(data); if not ok then f:close(); return ok, msg, "write"; @@ -247,7 +240,7 @@ ok, msg = f:close(); if not ok then - return ok, msg; + return ok, msg, "close"; end return true, pos; @@ -259,9 +252,10 @@ -- save the datastore data = "item(" .. serialize(data) .. ");\n"; - local ok, msg = append(username, host, datastore, "list", data); + local ok, msg, where = append(username, host, datastore, "list", data); if not ok then - log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil"); + log("error", "Unable to write to %s storage ('%s' in %s) for user: %s@%s", + datastore, msg, where, username or "nil", host or "nil"); return ok, msg; end return true;