1 ---------------------------------
2 --- @file namespaces.lua
3 --- @brief Namespaces ...
5 ---------------------------------
9 local
ffi = require
"ffi"
10 local serpent = require
"Serpent"
11 local stp = require
"StackTracePlus"
12 local lock = require
"lock"
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);
23 local cbType =
ffi.typeof(
"void (*)(const char* key, const char* val)")
28 namespace.__index =
namespace
30 local
function getNameFromTrace()
31 return debug.traceback():match("\
n.-\
n.-\
n(.-)\
n")
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
37 name = name or getNameFromTrace()
38 return C.create_or_get_namespace(name)
41 --- Retrieve a *copy* of a value in the namespace.
42 --- @param key the key, must be a
string
44 if type(key) ~= "
string" then
45 error("table index must be a
string")
49 elseif key == "lock" then
50 return C.namespace_get_lock(self)
52 local val = C.namespace_retrieve(self, key)
53 return val ~= nil and loadstring(
ffi.
string(val))() or nil
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
60 if type(key) ~= "
string" then
61 error("table index must be a
string")
63 if key == "
forEach" or key == "lock" then
64 error(key .. " is reserved", 2)
67 C.namespace_delete(self, key)
69 C.namespace_store(self, key, serpent.
dump(val))
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)
81 local cb =
ffi.cast(cbType, function(key, val)
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))())
94 C.namespace_iterate(self, cb)
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)
102 ffi.metatype("struct namespace", namespace)
local ffi
low-level dpdk wrapper
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
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).
namespace forEach(func)
Iterate over all keys/values in a namespace Note: namespaces do not offer a 'normal' iterator (e...