util/datamanager.lua
author Kim Alvefur <zash@zash.se>
Fri, 11 Dec 2015 20:30:39 +0100
changeset 7003 2b57f77985a3
parent 7002 0ad66d12113a
child 7004 2743759ca1b5
permissions -rw-r--r--
util.datamanager: Make sure only strings are passed as data to append()
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1523
841d61be198f Remove version number from copyright headers
Matthew Wild <mwild1@gmail.com>
parents: 1462
diff changeset
     1
-- Prosody IM
2923
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 2159
diff changeset
     2
-- Copyright (C) 2008-2010 Matthew Wild
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 2159
diff changeset
     3
-- Copyright (C) 2008-2010 Waqas Hussain
4452
7de17ca4de14 util/datamanager: Use package.config to figure out directory seperator
James Callahan <james@chatid.com>
parents: 4112
diff changeset
     4
--
758
b1885732e979 GPL->MIT!
Matthew Wild <mwild1@gmail.com>
parents: 732
diff changeset
     5
-- This project is MIT/X11 licensed. Please see the
b1885732e979 GPL->MIT!
Matthew Wild <mwild1@gmail.com>
parents: 732
diff changeset
     6
-- COPYING file in the source package for more information.
519
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 456
diff changeset
     7
--
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 456
diff changeset
     8
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 456
diff changeset
     9
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    10
local format = string.format;
5051
71253db26fda util.datamanager: Remove a few unused imports
Kim Alvefur <zash@zash.se>
parents: 5049
diff changeset
    11
local setmetatable = setmetatable;
71253db26fda util.datamanager: Remove a few unused imports
Kim Alvefur <zash@zash.se>
parents: 5049
diff changeset
    12
local ipairs = ipairs;
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    13
local char = string.char;
5021
85b2689dbcfe Eliminate direct setfenv usage
Florian Zeitz <florob@babelmonkeys.de>
parents: 4452
diff changeset
    14
local pcall = pcall;
456
27cb85d4059e Fixed logging in datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 452
diff changeset
    15
local log = require "util.logger".init("datamanager");
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    16
local io_open = io.open;
206
e30d0e30a0ff Datamanager now deletes files with no data
Waqas Hussain <waqas20@gmail.com>
parents: 182
diff changeset
    17
local os_remove = os.remove;
5049
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
    18
local os_rename = os.rename;
5051
71253db26fda util.datamanager: Remove a few unused imports
Kim Alvefur <zash@zash.se>
parents: 5049
diff changeset
    19
local tonumber = tonumber;
206
e30d0e30a0ff Datamanager now deletes files with no data
Waqas Hussain <waqas20@gmail.com>
parents: 182
diff changeset
    20
local next = next;
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
    21
local t_insert = table.insert;
5049
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
    22
local t_concat = table.concat;
5021
85b2689dbcfe Eliminate direct setfenv usage
Florian Zeitz <florob@babelmonkeys.de>
parents: 4452
diff changeset
    23
local envloadfile = require"util.envload".envloadfile;
5045
4ba6940deed0 util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Kim Alvefur <zash@zash.se>
parents: 5038
diff changeset
    24
local serialize = require "util.serialization".serialize;
4452
7de17ca4de14 util/datamanager: Use package.config to figure out directory seperator
James Callahan <james@chatid.com>
parents: 4112
diff changeset
    25
local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.config not in standard form" ) -- Extract directory seperator from package.config (an undocumented string that comes with lua)
3086
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
    26
local lfs = require "lfs";
4093
36555949bd16 util.datamanager: Use prosody.paths.data as the initial value for data_path
Matthew Wild <mwild1@gmail.com>
parents: 3723
diff changeset
    27
local prosody = prosody;
2444
267d6482bac6 util.datamanager: Use pposix.mkdir if available
Matthew Wild <mwild1@gmail.com>
parents: 2328
diff changeset
    28
5118
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    29
local raw_mkdir = lfs.mkdir;
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    30
local function fallocate(f, offset, len)
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    31
	-- This assumes that current position == offset
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    32
	local fake_data = (" "):rep(len);
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    33
	local ok, msg = f:write(fake_data);
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    34
	if not ok then
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    35
		return ok, msg;
5045
4ba6940deed0 util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Kim Alvefur <zash@zash.se>
parents: 5038
diff changeset
    36
	end
5118
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    37
	f:seek("set", offset);
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    38
	return true;
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    39
end;
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    40
pcall(function()
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    41
	local pposix = require "util.pposix";
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    42
	raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    43
	fallocate = pposix.fallocate or fallocate;
0dc9e6c128c3 util.datamanager: Make the util.pposix dependency optional.
Waqas Hussain <waqas20@gmail.com>
parents: 5103
diff changeset
    44
end);
5045
4ba6940deed0 util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Kim Alvefur <zash@zash.se>
parents: 5038
diff changeset
    45
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
    46
local _ENV = nil;
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    47
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    48
---- utils -----
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    49
local encode, decode;
2444
267d6482bac6 util.datamanager: Use pposix.mkdir if available
Matthew Wild <mwild1@gmail.com>
parents: 2328
diff changeset
    50
do
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    51
	local urlcodes = setmetatable({}, { __index = function (t, k) t[k] = char(tonumber("0x"..k)); return t[k]; end });
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    52
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    53
	decode = function (s)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    54
		return s and (s:gsub("+", " "):gsub("%%([a-fA-F0-9][a-fA-F0-9])", urlcodes));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    55
	end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    56
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    57
	encode = function (s)
628
3712d36b6d25 Fixed URL encoding to generate %0x instead of %x
Waqas Hussain <waqas20@gmail.com>
parents: 615
diff changeset
    58
		return s and (s:gsub("%W", function (c) return format("%%%02x", c:byte()); end));
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    59
	end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    60
end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    61
643
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    62
local _mkdir = {};
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    63
local function mkdir(path)
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    64
	path = path:gsub("/", path_separator); -- TODO as an optimization, do this during path creation rather than here
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    65
	if not _mkdir[path] then
2444
267d6482bac6 util.datamanager: Use pposix.mkdir if available
Matthew Wild <mwild1@gmail.com>
parents: 2328
diff changeset
    66
		raw_mkdir(path);
643
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    67
		_mkdir[path] = true;
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    68
	end
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    69
	return path;
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    70
end
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    71
4108
e3e3aa286334 util.datamanager: Handle gracefully the lack of prosody.paths.data
Matthew Wild <mwild1@gmail.com>
parents: 4093
diff changeset
    72
local data_path = (prosody and prosody.paths and prosody.paths.data) or ".";
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    73
local callbacks = {};
643
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
    74
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    75
------- API -------------
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    76
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
    77
local function set_data_path(path)
1097
c5b33640a5f0 util.datamanager: Lower log level of 'Setting data path' to 'debug'
Matthew Wild <mwild1@gmail.com>
parents: 932
diff changeset
    78
	log("debug", "Setting data path to: %s", path);
452
613c5c6bdce4 Added option core.data_path
Waqas Hussain <waqas20@gmail.com>
parents: 267
diff changeset
    79
	data_path = path;
613c5c6bdce4 Added option core.data_path
Waqas Hussain <waqas20@gmail.com>
parents: 267
diff changeset
    80
end
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    81
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    82
local function callback(username, host, datastore, data)
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    83
	for _, f in ipairs(callbacks) do
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    84
		username, host, datastore, data = f(username, host, datastore, data);
1462
44780b856ce7 datamanager: Fixed incorrect callback result checking
Waqas Hussain <waqas20@gmail.com>
parents: 1381
diff changeset
    85
		if username == false then break; end
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    86
	end
4452
7de17ca4de14 util/datamanager: Use package.config to figure out directory seperator
James Callahan <james@chatid.com>
parents: 4112
diff changeset
    87
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    88
	return username, host, datastore, data;
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    89
end
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
    90
local function add_callback(func)
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    91
	if not callbacks[func] then -- Would you really want to set the same callback more than once?
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    92
		callbacks[func] = true;
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    93
		callbacks[#callbacks+1] = func;
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    94
		return true;
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    95
	end
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    96
end
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
    97
local function remove_callback(func)
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    98
	if callbacks[func] then
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
    99
		for i, f in ipairs(callbacks) do
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   100
			if f == func then
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   101
				callbacks[i] = nil;
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   102
				callbacks[f] = nil;
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   103
				return true;
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   104
			end
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   105
		end
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   106
	end
932
1ed3e5fe165a Added: datamanager: Allow a callback to be installed which selectively prevents disk writes
Waqas Hussain <waqas20@gmail.com>
parents: 915
diff changeset
   107
end
452
613c5c6bdce4 Added option core.data_path
Waqas Hussain <waqas20@gmail.com>
parents: 267
diff changeset
   108
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   109
local function getpath(username, host, datastore, ext, create)
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   110
	ext = ext or "dat";
2328
2804d81206d8 util.datamanager: Store data stores with no host in '_global' folder
Matthew Wild <mwild1@gmail.com>
parents: 2159
diff changeset
   111
	host = (host and encode(host)) or "_global";
643
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
   112
	username = username and encode(username);
84
d0a0bac6815e Added: Datastore support for hosts and global data in addition to users
Waqas Hussain <waqas20@gmail.com>
parents: 0
diff changeset
   113
	if username then
643
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
   114
		if create then mkdir(mkdir(mkdir(data_path).."/"..host).."/"..datastore); end
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
   115
		return format("%s/%s/%s/%s.%s", data_path, host, datastore, username, ext);
5243
07e8256efcda util.datamanager: Remove dead code path
Kim Alvefur <zash@zash.se>
parents: 5153
diff changeset
   116
	else
643
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
   117
		if create then mkdir(mkdir(data_path).."/"..host); end
8ff454831f7d Moved directory auto-creation to datamanager
Waqas Hussain <waqas20@gmail.com>
parents: 628
diff changeset
   118
		return format("%s/%s/%s.%s", data_path, host, datastore, ext);
84
d0a0bac6815e Added: Datastore support for hosts and global data in addition to users
Waqas Hussain <waqas20@gmail.com>
parents: 0
diff changeset
   119
	end
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   120
end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   121
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   122
local function load(username, host, datastore)
5021
85b2689dbcfe Eliminate direct setfenv usage
Florian Zeitz <florob@babelmonkeys.de>
parents: 4452
diff changeset
   123
	local data, ret = envloadfile(getpath(username, host, datastore), {});
117
8e5c5e6a3240 Fixed: datamanager.store and datamanager.load could crash when username or host arguments were nil. (useful for server specific and global data).
Waqas Hussain <waqas20@gmail.com>
parents: 88
diff changeset
   124
	if not data then
3086
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   125
		local mode = lfs.attributes(getpath(username, host, datastore), "mode");
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   126
		if not mode then
4993
5243b74a4cbb Hopefully inert commit to clean up logging across a number of modules, removing all cases of concatenation when building log messages
Matthew Wild <mwild1@gmail.com>
parents: 4452
diff changeset
   127
			log("debug", "Assuming empty %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
3086
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   128
			return nil;
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   129
		else -- file exists, but can't be read
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   130
			-- TODO more detailed error checking and logging?
4993
5243b74a4cbb Hopefully inert commit to clean up logging across a number of modules, removing all cases of concatenation when building log messages
Matthew Wild <mwild1@gmail.com>
parents: 4452
diff changeset
   131
			log("error", "Failed to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
3086
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   132
			return nil, "Error reading storage";
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   133
		end
117
8e5c5e6a3240 Fixed: datamanager.store and datamanager.load could crash when username or host arguments were nil. (useful for server specific and global data).
Waqas Hussain <waqas20@gmail.com>
parents: 88
diff changeset
   134
	end
5021
85b2689dbcfe Eliminate direct setfenv usage
Florian Zeitz <florob@babelmonkeys.de>
parents: 4452
diff changeset
   135
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   136
	local success, ret = pcall(data);
117
8e5c5e6a3240 Fixed: datamanager.store and datamanager.load could crash when username or host arguments were nil. (useful for server specific and global data).
Waqas Hussain <waqas20@gmail.com>
parents: 88
diff changeset
   137
	if not success then
4993
5243b74a4cbb Hopefully inert commit to clean up logging across a number of modules, removing all cases of concatenation when building log messages
Matthew Wild <mwild1@gmail.com>
parents: 4452
diff changeset
   138
		log("error", "Unable to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
3086
931acb1188b1 util.datamanager: When failing to load a file, and the file exists, return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 2925
diff changeset
   139
		return nil, "Error reading storage";
117
8e5c5e6a3240 Fixed: datamanager.store and datamanager.load could crash when username or host arguments were nil. (useful for server specific and global data).
Waqas Hussain <waqas20@gmail.com>
parents: 88
diff changeset
   140
	end
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   141
	return ret;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   142
end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   143
5049
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   144
local function atomic_store(filename, data)
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   145
	local scratch = filename.."~";
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   146
	local f, ok, msg;
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   147
	repeat
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   148
		f, msg = io_open(scratch, "w");
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   149
		if not f then break end
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   150
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   151
		ok, msg = f:write(data);
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   152
		if not ok then break end
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   153
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   154
		ok, msg = f:close();
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   155
		if not ok then break end
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   156
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   157
		return os_rename(scratch, filename);
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   158
	until false;
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   159
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   160
	-- Cleanup
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   161
	if f then f:close(); end
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   162
	os_remove(scratch);
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   163
	return nil, msg;
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   164
end
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   165
6578
bdaadf70a48f util.datamanager: Check that the global 'prosody' exists before using it (fixes nil indexing in use outside of prosody)
Kim Alvefur <zash@zash.se>
parents: 5441
diff changeset
   166
if prosody and prosody.platform ~= "posix" then
5065
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   167
	-- os.rename does not overwrite existing files on Windows
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   168
	-- TODO We could use Transactional NTFS on Vista and above
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   169
	function atomic_store(filename, data)
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   170
		local f, err = io_open(filename, "w");
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   171
		if not f then return f, err; end
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   172
		local ok, msg = f:write(data);
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   173
		if not ok then f:close(); return ok, msg; end
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   174
		return f:close();
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   175
	end
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   176
end
acfaf771f10e util.datamanager: Don't use os.rename on non-POSIX. It doesn't overwrite exisitng files on Windows.
Waqas Hussain <waqas20@gmail.com>
parents: 5057
diff changeset
   177
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   178
local function store(username, host, datastore, data)
206
e30d0e30a0ff Datamanager now deletes files with no data
Waqas Hussain <waqas20@gmail.com>
parents: 182
diff changeset
   179
	if not data then
e30d0e30a0ff Datamanager now deletes files with no data
Waqas Hussain <waqas20@gmail.com>
parents: 182
diff changeset
   180
		data = {};
e30d0e30a0ff Datamanager now deletes files with no data
Waqas Hussain <waqas20@gmail.com>
parents: 182
diff changeset
   181
	end
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   182
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   183
	username, host, datastore, data = callback(username, host, datastore, data);
1462
44780b856ce7 datamanager: Fixed incorrect callback result checking
Waqas Hussain <waqas20@gmail.com>
parents: 1381
diff changeset
   184
	if username == false then
1381
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   185
		return true; -- Don't save this data at all
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   186
	end
46a58df8557d util.datamanager: Allow multiple data storage callbacks, and allow them to modify parameters
Matthew Wild <mwild1@gmail.com>
parents: 1097
diff changeset
   187
206
e30d0e30a0ff Datamanager now deletes files with no data
Waqas Hussain <waqas20@gmail.com>
parents: 182
diff changeset
   188
	-- save the datastore
5049
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   189
	local d = "return " .. serialize(data) .. ";\n";
5441
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   190
	local mkdir_cache_cleared;
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   191
	repeat
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   192
		local ok, msg = atomic_store(getpath(username, host, datastore, nil, true), d);
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   193
		if not ok then
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   194
			if not mkdir_cache_cleared then -- We may need to recreate a removed directory
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   195
				_mkdir = {};
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   196
				mkdir_cache_cleared = true;
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   197
			else
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   198
				log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   199
				return nil, "Error saving to storage";
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   200
			end
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   201
		end
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   202
		if next(data) == nil then -- try to delete empty datastore
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   203
			log("debug", "Removing empty %s datastore for user %s@%s", datastore, username or "nil", host or "nil");
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   204
			os_remove(getpath(username, host, datastore));
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   205
		end
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   206
		-- we write data even when we are deleting because lua doesn't have a
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   207
		-- platform independent way of checking for non-exisitng files
6a5c622cc6d4 util.datamanager: Clear the cache of created directories on storage failure, and retry
Matthew Wild <mwild1@gmail.com>
parents: 5440
diff changeset
   208
	until ok;
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   209
	return true;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   210
end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   211
7002
0ad66d12113a util.datamanager: Add some comments about the append function
Kim Alvefur <zash@zash.se>
parents: 7001
diff changeset
   212
-- Append a blob of data to a file
6995
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   213
local function append(username, host, datastore, ext, data)
7003
2b57f77985a3 util.datamanager: Make sure only strings are passed as data to append()
Kim Alvefur <zash@zash.se>
parents: 7002
diff changeset
   214
	if type(data) ~= "string" then return; end
6997
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   215
	local filename = getpath(username, host, datastore, ext, true);
6999
644b1bddc676 util.datamanager: No shadowing of variable [luacheck]
Kim Alvefur <zash@zash.se>
parents: 6998
diff changeset
   216
644b1bddc676 util.datamanager: No shadowing of variable [luacheck]
Kim Alvefur <zash@zash.se>
parents: 6998
diff changeset
   217
	local ok;
6997
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   218
	local f, msg = io_open(filename, "r+");
5066
4be7093edde9 util.datamanager: Try to open in read+write mode, then retry with write mode if that fails (usually because it doesn't exist)
Kim Alvefur <zash@zash.se>
parents: 5057
diff changeset
   219
	if not f then
7002
0ad66d12113a util.datamanager: Add some comments about the append function
Kim Alvefur <zash@zash.se>
parents: 7001
diff changeset
   220
		-- File did probably not exist, let's create it
6997
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   221
		f, msg = io_open(filename, "w");
6998
807b0b2ee545 util.datamanager: Skip past second check if first attemtp to open file succeeds
Kim Alvefur <zash@zash.se>
parents: 6997
diff changeset
   222
		if not f then
807b0b2ee545 util.datamanager: Skip past second check if first attemtp to open file succeeds
Kim Alvefur <zash@zash.se>
parents: 6997
diff changeset
   223
			return nil, msg;
807b0b2ee545 util.datamanager: Skip past second check if first attemtp to open file succeeds
Kim Alvefur <zash@zash.se>
parents: 6997
diff changeset
   224
		end
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   225
	end
7002
0ad66d12113a util.datamanager: Add some comments about the append function
Kim Alvefur <zash@zash.se>
parents: 7001
diff changeset
   226
5045
4ba6940deed0 util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Kim Alvefur <zash@zash.se>
parents: 5038
diff changeset
   227
	local pos = f:seek("end");
6999
644b1bddc676 util.datamanager: No shadowing of variable [luacheck]
Kim Alvefur <zash@zash.se>
parents: 6998
diff changeset
   228
	ok, msg = fallocate(f, pos, #data);
7000
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   229
	if not ok then
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   230
		log("warn", "fallocate() failed: %s", tostring(msg));
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   231
		-- This doesn't work on every file system
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   232
	end
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   233
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   234
	if f:seek() ~= pos then
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   235
		log("debug", "fallocate() changed file position");
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   236
		f:seek("set", pos);
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   237
	end
0ab228bc21c6 util.datamanager: Handle potential issues from fallocate
Kim Alvefur <zash@zash.se>
parents: 6999
diff changeset
   238
7001
86607fe755b6 util.datamanager: Handle potential error from :write() call
Kim Alvefur <zash@zash.se>
parents: 7000
diff changeset
   239
	ok, msg = f:write(data);
86607fe755b6 util.datamanager: Handle potential error from :write() call
Kim Alvefur <zash@zash.se>
parents: 7000
diff changeset
   240
	if not ok then
86607fe755b6 util.datamanager: Handle potential error from :write() call
Kim Alvefur <zash@zash.se>
parents: 7000
diff changeset
   241
		f:close();
6995
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   242
		return ok, msg;
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   243
	end
6997
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   244
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   245
	ok, msg = f:close();
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   246
	if not ok then
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   247
		return ok, msg;
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   248
	end
507301531cf5 util.datamanager: In append() collect status when closing file handle as it may fail (eg the implied flush)
Kim Alvefur <zash@zash.se>
parents: 6996
diff changeset
   249
6995
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   250
	return true;
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   251
end
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   252
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   253
local function list_append(username, host, datastore, data)
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   254
	if not data then return; end
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   255
	if callback(username, host, datastore) == false then return true; end
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   256
	-- save the datastore
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   257
6996
dc0c6b8dc638 util.datamanager: Overwrite 'data' variable instead of shadownig it [luacheck]
Kim Alvefur <zash@zash.se>
parents: 6995
diff changeset
   258
	data = "item(" ..  serialize(data) .. ");\n";
6995
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   259
	local ok, msg = append(username, host, datastore, "list", data);
0622f2820d1d util.datamanager: Factor out code for appending bytes to a file
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
   260
	if not ok then
5045
4ba6940deed0 util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Kim Alvefur <zash@zash.se>
parents: 5038
diff changeset
   261
		log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
4ba6940deed0 util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Kim Alvefur <zash@zash.se>
parents: 5038
diff changeset
   262
		return ok, msg;
4ba6940deed0 util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Kim Alvefur <zash@zash.se>
parents: 5038
diff changeset
   263
	end
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   264
	return true;
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   265
end
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   266
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   267
local function list_store(username, host, datastore, data)
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   268
	if not data then
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   269
		data = {};
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   270
	end
1462
44780b856ce7 datamanager: Fixed incorrect callback result checking
Waqas Hussain <waqas20@gmail.com>
parents: 1381
diff changeset
   271
	if callback(username, host, datastore) == false then return true; end
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   272
	-- save the datastore
5049
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   273
	local d = {};
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   274
	for _, item in ipairs(data) do
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   275
		d[#d+1] = "item(" .. serialize(item) .. ");\n";
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   276
	end
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   277
	local ok, msg = atomic_store(getpath(username, host, datastore, "list", true), t_concat(d));
5d685f123332 util.datamanager: Write to a temporary file and atomically move it into place
Kim Alvefur <zash@zash.se>
parents: 5045
diff changeset
   278
	if not ok then
4993
5243b74a4cbb Hopefully inert commit to clean up logging across a number of modules, removing all cases of concatenation when building log messages
Matthew Wild <mwild1@gmail.com>
parents: 4452
diff changeset
   279
		log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   280
		return;
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   281
	end
915
0fe5bf7ab81d util.datamanager: Don't delete data when first entry in table is 'false'. My favourite bug so far.
Matthew Wild <mwild1@gmail.com>
parents: 896
diff changeset
   282
	if next(data) == nil then -- try to delete empty datastore
1732
f1282fad2f99 datamanager: Fixed logging errors on deletion of datastores not owned by a user@host
Waqas Hussain <waqas20@gmail.com>
parents: 1523
diff changeset
   283
		log("debug", "Removing empty %s datastore for user %s@%s", datastore, username or "nil", host or "nil");
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   284
		os_remove(getpath(username, host, datastore, "list"));
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   285
	end
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   286
	-- we write data even when we are deleting because lua doesn't have a
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   287
	-- platform independent way of checking for non-exisitng files
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   288
	return true;
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   289
end
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   290
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   291
local function list_load(username, host, datastore)
5021
85b2689dbcfe Eliminate direct setfenv usage
Florian Zeitz <florob@babelmonkeys.de>
parents: 4452
diff changeset
   292
	local items = {};
85b2689dbcfe Eliminate direct setfenv usage
Florian Zeitz <florob@babelmonkeys.de>
parents: 4452
diff changeset
   293
	local data, ret = envloadfile(getpath(username, host, datastore, "list"), {item = function(i) t_insert(items, i); end});
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   294
	if not data then
3722
f15b6ed967b7 util.datamanager: When failing to load a list file, and the file exists, log an error, and return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 3108
diff changeset
   295
		local mode = lfs.attributes(getpath(username, host, datastore, "list"), "mode");
f15b6ed967b7 util.datamanager: When failing to load a list file, and the file exists, log an error, and return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 3108
diff changeset
   296
		if not mode then
4993
5243b74a4cbb Hopefully inert commit to clean up logging across a number of modules, removing all cases of concatenation when building log messages
Matthew Wild <mwild1@gmail.com>
parents: 4452
diff changeset
   297
			log("debug", "Assuming empty %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
3722
f15b6ed967b7 util.datamanager: When failing to load a list file, and the file exists, log an error, and return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 3108
diff changeset
   298
			return nil;
f15b6ed967b7 util.datamanager: When failing to load a list file, and the file exists, log an error, and return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 3108
diff changeset
   299
		else -- file exists, but can't be read
f15b6ed967b7 util.datamanager: When failing to load a list file, and the file exists, log an error, and return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 3108
diff changeset
   300
			-- TODO more detailed error checking and logging?
4993
5243b74a4cbb Hopefully inert commit to clean up logging across a number of modules, removing all cases of concatenation when building log messages
Matthew Wild <mwild1@gmail.com>
parents: 4452
diff changeset
   301
			log("error", "Failed to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
3722
f15b6ed967b7 util.datamanager: When failing to load a list file, and the file exists, log an error, and return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 3108
diff changeset
   302
			return nil, "Error reading storage";
f15b6ed967b7 util.datamanager: When failing to load a list file, and the file exists, log an error, and return nil, error.
Waqas Hussain <waqas20@gmail.com>
parents: 3108
diff changeset
   303
		end
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   304
	end
5021
85b2689dbcfe Eliminate direct setfenv usage
Florian Zeitz <florob@babelmonkeys.de>
parents: 4452
diff changeset
   305
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   306
	local success, ret = pcall(data);
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   307
	if not success then
4993
5243b74a4cbb Hopefully inert commit to clean up logging across a number of modules, removing all cases of concatenation when building log messages
Matthew Wild <mwild1@gmail.com>
parents: 4452
diff changeset
   308
		log("error", "Unable to load %s storage ('%s') for user: %s@%s", datastore, ret, username or "nil", host or "nil");
3723
72a917d910a4 util.datamanager: Return an error string when pcall fails on a loaded list file.
Waqas Hussain <waqas20@gmail.com>
parents: 3722
diff changeset
   309
		return nil, "Error reading storage";
247
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   310
	end
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   311
	return items;
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   312
end
681b29aa134f Added support for storing (and removing), loading and appending to lists of data to datamanager (for supporting offline messages)
Waqas Hussain <waqas20@gmail.com>
parents: 206
diff changeset
   313
5130
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   314
local type_map = {
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   315
	keyval = "dat";
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   316
	list = "list";
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   317
}
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   318
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   319
local function users(host, store, typ)
5153
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   320
	typ = type_map[typ or "keyval"];
5250
6d8ec8c90240 util.datamanager: Don't escape the name of a store
Kim Alvefur <zash@zash.se>
parents: 5244
diff changeset
   321
	local store_dir = format("%s/%s/%s", data_path, encode(host), store);
5153
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   322
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   323
	local mode, err = lfs.attributes(store_dir, "mode");
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   324
	if not mode then
6647
6cb6855f60df util.datamanager: Fix traceback due to %s in log message
Kim Alvefur <zash@zash.se>
parents: 6578
diff changeset
   325
		return function() log("debug", "%s", err or (store_dir .. " does not exist")) end
5153
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   326
	end
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   327
	local next, state = lfs.dir(store_dir);
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   328
	return function(state)
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   329
		for node in next, state do
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   330
			local file, ext = node:match("^(.*)%.([dalist]+)$");
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   331
			if file and ext == typ then
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   332
				return decode(file);
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   333
			end
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   334
		end
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   335
	end, state;
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   336
end
688aeac0012a mod_storage_internal, datamanager: Add support for iterating over users with data in a store
Kim Alvefur <zash@zash.se>
parents: 5130
diff changeset
   337
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   338
local function stores(username, host, typ)
5130
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   339
	typ = type_map[typ or "keyval"];
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   340
	local store_dir = format("%s/%s/", data_path, encode(host));
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   341
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   342
	local mode, err = lfs.attributes(store_dir, "mode");
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   343
	if not mode then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   344
		return function() log("debug", err or (store_dir .. " does not exist")) end
5032
c40ea227f8af util.datamanager: Add function for listing stores
Kim Alvefur <zash@zash.se>
parents: 5024
diff changeset
   345
	end
5130
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   346
	local next, state = lfs.dir(store_dir);
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   347
	return function(state)
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   348
		for node in next, state do
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   349
			if not node:match"^%." then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   350
				if username == true then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   351
					if lfs.attributes(store_dir..node, "mode") == "directory" then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   352
						return decode(node);
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   353
					end
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   354
				elseif username then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   355
					local store = decode(node)
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   356
					if lfs.attributes(getpath(username, host, store, typ), "mode") then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   357
						return store;
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   358
					end
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   359
				elseif lfs.attributes(node, "mode") == "file" then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   360
					local file, ext = node:match("^(.*)%.([dalist]+)$");
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   361
					if ext == typ then
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   362
						return decode(file)
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   363
					end
5032
c40ea227f8af util.datamanager: Add function for listing stores
Kim Alvefur <zash@zash.se>
parents: 5024
diff changeset
   364
				end
c40ea227f8af util.datamanager: Add function for listing stores
Kim Alvefur <zash@zash.se>
parents: 5024
diff changeset
   365
			end
c40ea227f8af util.datamanager: Add function for listing stores
Kim Alvefur <zash@zash.se>
parents: 5024
diff changeset
   366
		end
5130
051d352ed03c storagemanager, datamanager, mod_storage_{internal,sql}: Replace list_stores() with an iterator version
Kim Alvefur <zash@zash.se>
parents: 5118
diff changeset
   367
	end, state;
5032
c40ea227f8af util.datamanager: Add function for listing stores
Kim Alvefur <zash@zash.se>
parents: 5024
diff changeset
   368
end
c40ea227f8af util.datamanager: Add function for listing stores
Kim Alvefur <zash@zash.se>
parents: 5024
diff changeset
   369
5103
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   370
local function do_remove(path)
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   371
	local ok, err = os_remove(path);
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   372
	if not ok and lfs.attributes(path, "mode") then
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   373
		return ok, err;
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   374
	end
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   375
	return true
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   376
end
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   377
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   378
local function purge(username, host)
5038
242c62ff8e77 util.datamanager: Add function for removing all data belonging to a user
Kim Alvefur <zash@zash.se>
parents: 5032
diff changeset
   379
	local host_dir = format("%s/%s/", data_path, encode(host));
6684
0217a04722c7 util.datamanager: Fix traceback from trying to purge when storage is empty or otherwise unaccessible (fixes #496)
Kim Alvefur <zash@zash.se>
parents: 6647
diff changeset
   380
	local ok, iter, state, var = pcall(lfs.dir, host_dir);
0217a04722c7 util.datamanager: Fix traceback from trying to purge when storage is empty or otherwise unaccessible (fixes #496)
Kim Alvefur <zash@zash.se>
parents: 6647
diff changeset
   381
	if not ok then
0217a04722c7 util.datamanager: Fix traceback from trying to purge when storage is empty or otherwise unaccessible (fixes #496)
Kim Alvefur <zash@zash.se>
parents: 6647
diff changeset
   382
		return ok, iter;
0217a04722c7 util.datamanager: Fix traceback from trying to purge when storage is empty or otherwise unaccessible (fixes #496)
Kim Alvefur <zash@zash.se>
parents: 6647
diff changeset
   383
	end
5095
dddbcd62183a util.datamanager: Collect errors when deleting all stores of a user, but ignore "no such file"
Kim Alvefur <zash@zash.se>
parents: 5069
diff changeset
   384
	local errs = {};
6684
0217a04722c7 util.datamanager: Fix traceback from trying to purge when storage is empty or otherwise unaccessible (fixes #496)
Kim Alvefur <zash@zash.se>
parents: 6647
diff changeset
   385
	for file in iter, state, var do
5038
242c62ff8e77 util.datamanager: Add function for removing all data belonging to a user
Kim Alvefur <zash@zash.se>
parents: 5032
diff changeset
   386
		if lfs.attributes(host_dir..file, "mode") == "directory" then
242c62ff8e77 util.datamanager: Add function for removing all data belonging to a user
Kim Alvefur <zash@zash.se>
parents: 5032
diff changeset
   387
			local store = decode(file);
5103
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   388
			local ok, err = do_remove(getpath(username, host, store));
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   389
			if not ok then errs[#errs+1] = err; end
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   390
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   391
			local ok, err = do_remove(getpath(username, host, store, "list"));
5a1488369c35 util.datamanager: Ignore errors if the file is gone after removing it
Kim Alvefur <zash@zash.se>
parents: 5095
diff changeset
   392
			if not ok then errs[#errs+1] = err; end
5038
242c62ff8e77 util.datamanager: Add function for removing all data belonging to a user
Kim Alvefur <zash@zash.se>
parents: 5032
diff changeset
   393
		end
242c62ff8e77 util.datamanager: Add function for removing all data belonging to a user
Kim Alvefur <zash@zash.se>
parents: 5032
diff changeset
   394
	end
5095
dddbcd62183a util.datamanager: Collect errors when deleting all stores of a user, but ignore "no such file"
Kim Alvefur <zash@zash.se>
parents: 5069
diff changeset
   395
	return #errs == 0, t_concat(errs, ", ");
5038
242c62ff8e77 util.datamanager: Add function for removing all data belonging to a user
Kim Alvefur <zash@zash.se>
parents: 5032
diff changeset
   396
end
242c62ff8e77 util.datamanager: Add function for removing all data belonging to a user
Kim Alvefur <zash@zash.se>
parents: 5032
diff changeset
   397
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   398
return {
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   399
	set_data_path = set_data_path;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   400
	add_callback = add_callback;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   401
	remove_callback = remove_callback;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   402
	getpath = getpath;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   403
	load = load;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   404
	store = store;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   405
	list_append = list_append;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   406
	list_store = list_store;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   407
	list_load = list_load;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   408
	users = users;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   409
	stores = stores;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   410
	purge = purge;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   411
	path_decode = decode;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   412
	path_encode = encode;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6684
diff changeset
   413
};