跟踪对表的访问

简介: 跟踪对表的访问

加入我们要跟踪对某个表的所有访问。由于 __index__newindex 元方法都是在表中的索引不存在的时候才有用,因此,捕获对一个表所有访问的唯一方式是保持表是空的。如果要监控对一个表的所有访问,那么需要为真正的表创建一个代理proxy )。这个代理是一个空的表,具有用于跟踪所有访问并将访问重定向到原来的表的合理方法。

function track (t)
  local proxy = {}          -- ‘t’的代理表
  -- 为代理创建元表
  local mt = {
    __index = function (_, k)
      print("*access to element " .. tostring(k))
      return t[k]                                           -- 访问原来的表
    end,
    __newindex = function (_, k, v)
      print("*update of element " .. tostring(k) .. " to " .. tostring(v))
      t[k] = v          -- 更新原来的表
    end,
    __pairs = function ()
      return function (_, k)                                    -- 迭代函数
        local nextkey, nextvalue = next(t, k)
        if nextkey ~= nil then                                  -- 避免最后一个值
          print("*traversing element " .. tostring(nextkey))
        end
        return nextkey, nextvalue
      end
    end,
    __len = function () return #t end
  }
  setmetatable(proxy, mt)
  return proxy
end


以下展示了上述代码的用法:

> t = {}
> t = track(t)
> t[2] = "hello"    --> *update of element 2 to hello
> print(t[2])       --> *access to element 2
                    --> hello


元方法 __index__newindex 按照我们设计的规则跟踪每一个访问并将其重定向到原来的表中。元方法 __pairs 使得我们能够像遍历原来的表一样遍历代理,从而跟踪所有的访问。最后,元方法 __len 通过代理实现了长度操作符:

t = track({10, 20})
print(#t)                                     --> 2
for k, v in pairs(t) do print(k, v) end
--> *traversing element 1
--> 1    10
--> *traversing element 2
--> 2    20


如果想要同时监控几个表,并不需要为每个表创建不同的元表。相反,只要以某种形式将每个代理与其原始表映射起来,并且让所有的代理共享一个公共的元表即可。这个问题与把表与其默认值关联起来的问题类似,因此可以采用相同的解决方式。例如,可以把原来的表保存在代理表的一个特殊的字段中,或者使用一个对偶表示建立代理与相应表的映射。

目录
相关文章
|
8月前
|
关系型数据库 MySQL 数据库
InnoDB事务和锁定信息:如何识别和解决阻塞查询问题
InnoDB事务和锁定信息:如何识别和解决阻塞查询问题
|
4月前
|
数据库
数据库防止误删操作——打数据标记
数据库防止误删操作——打数据标记
56 1
|
SQL 存储 Oracle
为什么数据库有时候不能定位阻塞(Blocker)源头的SQL语句
原文:为什么数据库有时候不能定位阻塞(Blocker)源头的SQL语句     在SQL Server数据库或OACLE数据库当中,通常一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking)。
998 0

热门文章

最新文章