luci-base: cbi: atomically reorder uci sections
authorJo-Philipp Wich <jo@mein.io>
Thu, 31 May 2018 13:39:43 +0000 (15:39 +0200)
committerJo-Philipp Wich <jo@mein.io>
Sun, 3 Jun 2018 18:02:44 +0000 (20:02 +0200)
Since the switch to ubus uci operations we do not have a local application-
side cursor cache anymore, instead uci operations happen synchronously in
the rpcd backend server.

This may cause cbi section reorder operations involving multiple elements
to fail, because anonymous section hashes may change due to rehashing
between consecutive ubus uci reorder calls.

In order to avoid that problem, use the ubus uci batch reorder extension,
which allows to pass a complete (or partial) list of section ids in the
desired order in one call, bypassing the volatile section id problem.

Fixes #1844.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/luasrc/cbi.lua

index 4728642118c5d3794a3b5f9d7f25389bcf5c8743..4800d2aa72d71de202944605b9bdc204a5cac3aa 100644 (file)
@@ -1226,13 +1226,14 @@ function TypedSection.parse(self, novld)
                local stval = RESORT_PREFIX .. self.config .. "." .. self.sectiontype
                local order = self.map:formvalue(stval)
                if order and #order > 0 then
-                       local sid
-                       local num = 0
+                       local sids, sid = { }, nil
                        for sid in util.imatch(order) do
-                               self.map.uci:reorder(self.config, sid, num)
-                               num = num + 1
+                               sids[#sids+1] = sid
+                       end
+                       if #sids > 0 then
+                               self.map.uci:reorder(self.config, sids)
+                               self.changed = true
                        end
-                       self.changed = (num > 0)
                end
        end