Software /
code /
prosody
Comparison
util/datamanager.lua @ 8011:f8ba814fe029
util.datamanager: Use pposix.atomic_append
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 28 Feb 2017 11:33:43 +0100 |
parent | 7996:f4c0fb54e16c |
child | 8013:72cfbe377326 |
comparison
equal
deleted
inserted
replaced
8010:49feb0da29e1 | 8011:f8ba814fe029 |
---|---|
15 local log = require "util.logger".init("datamanager"); | 15 local log = require "util.logger".init("datamanager"); |
16 local io_open = io.open; | 16 local io_open = io.open; |
17 local os_remove = os.remove; | 17 local os_remove = os.remove; |
18 local os_rename = os.rename; | 18 local os_rename = os.rename; |
19 local tonumber = tonumber; | 19 local tonumber = tonumber; |
20 local tostring = tostring; | |
21 local next = next; | 20 local next = next; |
22 local type = type; | 21 local type = type; |
23 local t_insert = table.insert; | 22 local t_insert = table.insert; |
24 local t_concat = table.concat; | 23 local t_concat = table.concat; |
25 local envloadfile = require"util.envload".envloadfile; | 24 local envloadfile = require"util.envload".envloadfile; |
29 local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.config not in standard form" ) | 28 local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.config not in standard form" ) |
30 | 29 |
31 local prosody = prosody; | 30 local prosody = prosody; |
32 | 31 |
33 local raw_mkdir = lfs.mkdir; | 32 local raw_mkdir = lfs.mkdir; |
34 local function fallocate(f, offset, len) | 33 local atomic_append; |
35 -- This assumes that current position == offset | |
36 local fake_data = (" "):rep(len); | |
37 local ok, msg = f:write(fake_data); | |
38 if not ok then | |
39 return ok, msg; | |
40 end | |
41 f:seek("set", offset); | |
42 return true; | |
43 end; | |
44 local ENOENT = 2; | 34 local ENOENT = 2; |
45 pcall(function() | 35 pcall(function() |
46 local pposix = require "util.pposix"; | 36 local pposix = require "util.pposix"; |
47 raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask | 37 raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask |
48 fallocate = pposix.fallocate or fallocate; | 38 atomic_append = pposix.atomic_append; |
49 ENOENT = pposix.ENOENT or ENOENT; | 39 ENOENT = pposix.ENOENT or ENOENT; |
50 end); | 40 end); |
51 | 41 |
52 local _ENV = nil; | 42 local _ENV = nil; |
53 | 43 |
60 return s and (s:gsub("%%(%x%x)", urlcodes)); | 50 return s and (s:gsub("%%(%x%x)", urlcodes)); |
61 end | 51 end |
62 | 52 |
63 encode = function (s) | 53 encode = function (s) |
64 return s and (s:gsub("%W", function (c) return format("%%%02x", c:byte()); end)); | 54 return s and (s:gsub("%W", function (c) return format("%%%02x", c:byte()); end)); |
55 end | |
56 end | |
57 | |
58 if not atomic_append then | |
59 function atomic_append(f, data) | |
60 local pos = f:seek(); | |
61 if not f:write(data) or not f:flush() then | |
62 f:seek("set", pos); | |
63 f:write((" "):rep(#data)); | |
64 f:flush(); | |
65 return nil, "write-failed"; | |
66 end | |
67 return true; | |
65 end | 68 end |
66 end | 69 end |
67 | 70 |
68 local _mkdir = {}; | 71 local _mkdir = {}; |
69 local function mkdir(path) | 72 local function mkdir(path) |
219 local function append(username, host, datastore, ext, data) | 222 local function append(username, host, datastore, ext, data) |
220 if type(data) ~= "string" then return; end | 223 if type(data) ~= "string" then return; end |
221 local filename = getpath(username, host, datastore, ext, true); | 224 local filename = getpath(username, host, datastore, ext, true); |
222 | 225 |
223 local ok; | 226 local ok; |
224 local f, msg = io_open(filename, "r+"); | 227 local f, msg, errno = io_open(filename, "r+"); |
225 if not f then | 228 if not f then |
226 return atomic_store(filename, data); | 229 return atomic_store(filename, data); |
227 -- File did probably not exist, let's create it | 230 -- File did probably not exist, let's create it |
228 end | 231 end |
229 | 232 |
230 local pos = f:seek("end"); | 233 local pos = f:seek("end"); |
231 ok, msg = fallocate(f, pos, #data); | 234 |
232 if not ok then | 235 ok, msg = atomic_append(f, data); |
233 log("warn", "fallocate() failed: %s", tostring(msg)); | 236 |
234 -- This doesn't work on every file system | |
235 end | |
236 | |
237 if f:seek() ~= pos then | |
238 log("debug", "fallocate() changed file position"); | |
239 f:seek("set", pos); | |
240 end | |
241 | |
242 ok, msg = f:write(data); | |
243 if not ok then | 237 if not ok then |
244 f:close(); | 238 f:close(); |
245 return ok, msg, "write"; | 239 return ok, msg, "write"; |
246 end | 240 end |
247 | 241 |