MoonGen
 All Files Functions Variables Pages
namespaces.lua
Go to the documentation of this file.
1 ---------------------------------
2 --- @file namespaces.lua
3 --- @brief Namespaces ...
4 --- @todo TODO docu
5 ---------------------------------
6 
7 local mod = {}
8 
9 local ffi = require "ffi"
10 local serpent = require "Serpent"
11 local stp = require "StackTracePlus"
12 local lock = require "lock"
13 
14 ffi.cdef [[
15  struct namespace { };
16  struct namespace* create_or_get_namespace(const char* name);
17  void namespace_store(struct namespace* ns, const char* key, const char* value);
18  void namespace_delete(struct namespace* ns, const char* key);
19  const char* namespace_retrieve(struct namespace* ns, const char* key);
20  void namespace_iterate(struct namespace* ns, void (*func)(const char* key, const char* val));
21  struct lock* namespace_get_lock(struct namespace* ns);
22 ]]
23 local cbType = ffi.typeof("void (*)(const char* key, const char* val)")
24 
25 local C = ffi.C
26 
27 local namespace = {}
28 namespace.__index = namespace
29 
30 local function getNameFromTrace()
31  return debug.traceback():match("\n.-\n.-\n(.-)\n")
32 end
33 
34 --- Get a namespace by its name creating it if necessary.
35 --- @param name the name, defaults to an auto-generated string consisting of the caller's filename and line number
36 function mod:get(name)
37  name = name or getNameFromTrace()
38  return C.create_or_get_namespace(name)
39 end
40 
41 --- Retrieve a *copy* of a value in the namespace.
42 --- @param key the key, must be a string
43 function namespace:__index(key)
44  if type(key) ~= "string" then
45  error("table index must be a string")
46  end
47  if key == "forEach" then
48  return namespace.forEach
49  elseif key == "lock" then
50  return C.namespace_get_lock(self)
51  end
52  local val = C.namespace_retrieve(self, key)
53  return val ~= nil and loadstring(ffi.string(val))() or nil
54 end
55 
56 --- Store a value in the namespace.
57 --- @param key the key, must be a string
58 --- @param val the value to store, will be serialized
59 function namespace:__newindex(key, val)
60  if type(key) ~= "string" then
61  error("table index must be a string")
62  end
63  if key == "forEach" or key == "lock" then
64  error(key .. " is reserved", 2)
65  end
66  if val == nil then
67  C.namespace_delete(self, key)
68  else
69  C.namespace_store(self, key, serpent.dump(val))
70  end
71 end
72 
73 
74 --- Iterate over all keys/values in a namespace
75 --- Note: namespaces do not offer a 'normal' iterator (e.g. through a __pair metamethod) due to locking.
76 --- Iterating over a table requires a lock on the whole table; ensuring that the lock is released is
77 --- easier with a forEach method than with a regular iterator.
78 --- @param func function to call, receives (key, value) as arguments
79 function namespace:forEach(func)
80  local caughtError
81  local cb = ffi.cast(cbType, function(key, val)
82  if caughtError then
83  return
84  end
85  -- avoid throwing an error across the C++ frame unnecessarily
86  -- not sure if this would work properly when compiled with clang instead of gcc
87  local ok, err = xpcall(func, function(err)
88  return stp.stacktrace(err)
89  end, ffi.string(key), loadstring(ffi.string(val))())
90  if not ok then
91  caughtError = err
92  end
93  end)
94  C.namespace_iterate(self, cb)
95  cb:free()
96  if caughtError then
97  -- this is gonna be an ugly error message, but at least we get the full call stack
98  error("error while calling callback, inner error: " .. caughtError)
99  end
100 end
101 
102 ffi.metatype("struct namespace", namespace)
103 
104 return mod
105 
local ffi
low-level dpdk wrapper
Definition: dpdkc.lua:6
namespace __newindex(key, val)
Store a value in the namespace.
function mod free(buf)
Free off-heap allocated object.
function pkt dump(bytes)
Dumps the packet data cast to the best fitting packet struct.
namespace __index(key)
Retrieve a copy of a value in the namespace.
local mod
high-level dpdk wrapper
Definition: dpdk.lua:6
function mod get(name)
Get a namespace by its name creating it if necessary.
n
Create a new array of memory buffers (initialized to nil).
Definition: memory.lua:76
namespace forEach(func)
Iterate over all keys/values in a namespace Note: namespaces do not offer a 'normal' iterator (e...