summaryrefslogtreecommitdiffstats
path: root/acf2/transaction/backend.lua
diff options
context:
space:
mode:
Diffstat (limited to 'acf2/transaction/backend.lua')
-rw-r--r--acf2/transaction/backend.lua70
1 files changed, 70 insertions, 0 deletions
diff --git a/acf2/transaction/backend.lua b/acf2/transaction/backend.lua
new file mode 100644
index 0000000..79ea83a
--- /dev/null
+++ b/acf2/transaction/backend.lua
@@ -0,0 +1,70 @@
+--[[
+Copyright (c) 2012-2013 Kaarle Ritvanen
+See LICENSE file for license details
+--]]
+
+local M = {}
+
+local err = require('acf2.error')
+
+-- TODO each transaction backend (i.e. persistence manager or
+-- transaction proper) should be implemented as a thread or have its
+-- internal state stored in shared storage (with appropriate locking)
+
+
+local generation = 0
+function M.gen_number()
+ generation = generation + 1
+ return generation
+end
+
+
+M.TransactionBackend = require('acf2.object').class()
+
+function M.TransactionBackend:init() self.mod_time = {} end
+
+function M.TransactionBackend:get_if_older(path, timestamp)
+ local value, ts = self:get(path)
+ if ts > timestamp then err.raise('conflict', path) end
+ return value, ts
+end
+
+function M.TransactionBackend:set(path, value)
+ self:set_multiple{{path, value}}
+end
+
+function M.TransactionBackend:set_multiple(mods)
+ -- TODO delegate to PM backends?
+ local timestamp = M.gen_number()
+ local effective = {}
+
+ local function tostr(s) return s ~= nil and tostring(s) or nil end
+
+ for _, mod in ipairs(mods) do
+ local path, value = unpack(mod)
+
+ if type(value) == 'table' or type(
+ self:get(path)
+ ) == 'table' or self:get(path) ~= value then
+
+ table.insert(effective, mod)
+ self.mod_time[path] = timestamp
+ end
+ end
+
+ self:_set_multiple(effective)
+end
+
+-- TODO should be atomic, mutex with set_multiple
+function M.TransactionBackend:comp_and_setm(accessed, mods)
+ local errors = err.ErrorDict()
+ for path, timestamp in pairs(accessed) do
+ errors:collect(self.get_if_older, self, path, timestamp)
+ end
+ errors:raise()
+
+ self:set_multiple(mods)
+end
+
+
+return M