258 return true, pos; |
258 return true, pos; |
259 end |
259 end |
260 |
260 |
261 local index_fmt, index_item_size, index_magic; |
261 local index_fmt, index_item_size, index_magic; |
262 if string.packsize then |
262 if string.packsize then |
263 index_fmt = "TT"; -- struct { size_t start, size_t length } |
263 index_fmt = "T"; -- offset to the end of the item, length can be derived from two index items |
264 index_item_size = string.packsize(index_fmt); |
264 index_item_size = string.packsize(index_fmt); |
265 index_magic = string.pack(index_fmt, 7767639, 1); -- Magic string: T9 for "prosody", version number |
265 index_magic = string.pack(index_fmt, 7767639 + 1); -- Magic string: T9 for "prosody", version number |
266 end |
266 end |
267 |
267 |
268 local function list_append(username, host, datastore, data) |
268 local function list_append(username, host, datastore, data) |
269 if not data then return; end |
269 if not data then return; end |
270 if callback(username, host, datastore) == false then return true; end |
270 if callback(username, host, datastore) == false then return true; end |
277 datastore, msg, where, username or "nil", host or "nil"); |
277 datastore, msg, where, username or "nil", host or "nil"); |
278 return ok, msg; |
278 return ok, msg; |
279 end |
279 end |
280 if string.packsize then |
280 if string.packsize then |
281 local offset = type(msg) == "number" and msg or 0; |
281 local offset = type(msg) == "number" and msg or 0; |
282 local index_entry = string.pack(index_fmt, offset, #data); |
282 local index_entry = string.pack(index_fmt, offset + #data); |
283 if offset == 0 then |
283 if offset == 0 then |
284 index_entry = index_magic .. index_entry; |
284 index_entry = index_magic .. index_entry; |
285 end |
285 end |
286 local ok, off = append(username, host, datastore, "lidx", index_entry); |
286 local ok, off = append(username, host, datastore, "lidx", index_entry); |
287 off = off or 0; |
287 off = off or 0; |
356 end |
356 end |
357 |
357 |
358 local function store_list_index(username, host, datastore, index) |
358 local function store_list_index(username, host, datastore, index) |
359 local data = { index_magic }; |
359 local data = { index_magic }; |
360 for i, v in ipairs(index) do |
360 for i, v in ipairs(index) do |
361 data[i + 1] = string.pack(index_fmt, v.start, v.length); |
361 data[i + 1] = string.pack(index_fmt, v.start + v.length); |
362 end |
362 end |
363 local filename = getpath(username, host, datastore, "lidx"); |
363 local filename = getpath(username, host, datastore, "lidx"); |
364 return atomic_store(filename, t_concat(data)); |
364 return atomic_store(filename, t_concat(data)); |
365 end |
365 end |
366 |
366 |
367 local index_mt = { |
367 local index_mt = { |
368 __index = function(t, i) |
368 __index = function(t, i) |
369 if type(i) ~= "number" or i % 1 ~= 0 or i < 1 then |
369 if type(i) ~= "number" or i % 1 ~= 0 or i < 0 then |
370 return |
370 return |
371 end |
371 end |
372 if i < 0 then |
372 if i <= 0 then |
373 return |
373 return 0 |
374 end |
374 end |
375 local fh = t.file; |
375 local fh = t.file; |
376 local pos = i * index_item_size; |
376 local pos = (i - 1) * index_item_size; |
377 if fh:seek("set", pos) ~= pos then |
377 if fh:seek("set", pos) ~= pos then |
378 return nil |
378 return nil |
379 end |
379 end |
380 local data = fh:read(index_item_size); |
380 local data = fh:read(index_item_size * 2); |
381 if not data then |
381 if not data or #data ~= index_item_size * 2 then |
382 return nil |
382 return nil |
383 end |
383 end |
384 local start, length = string.unpack(index_fmt, data); |
384 local start, next_pos = string.unpack(index_fmt .. index_fmt, data); |
|
385 if pos == 0 then |
|
386 start = 0 |
|
387 end |
|
388 local length = next_pos - start; |
385 local v = { start = start; length = length }; |
389 local v = { start = start; length = length }; |
386 t[i] = v; |
390 t[i] = v; |
387 return v; |
391 return v; |
388 end; |
392 end; |
389 __len = function(t) |
393 __len = function(t) |