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;