Document the new "box.lib" module
Nobody has claimed this yet.
- Dominant language
- CSS
- Stars
- 15
- Forks
- 49
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 3
Description
Product: Tarantool
Since: 2.8.1
Root document: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box/
SME: @ cyrillos
ToDo
- Create a new section for this new submodule in the
boxreference (https://www.tarantool.io/en/doc/latest/reference/reference_lua/box/) - Add the description of the submodule according to the input below
Overview
box.lib module provides a way to create, delete and execute
C procedures from shared libraries. Unlike box.schema.func
methods the functions created with box.lib help are not persistent
and live purely in memory. Once a node get turned off they are
vanished. An initial purpose for them is to execute them on
nodes which are running in read-only mode.
Module functions
box.lib.load(path) -> obj | error
Loads a module from path and return an object instance
associate with the module, otherwise an error is thrown.
The path should not end up with shared library extension
(such as .so), only a file name shall be there.
Possible errors:
- IllegalParams: module path is either not supplied
or not a string. - SystemError: unable to open a module due to a system error.
- ClientError: a module does not exist.
- OutOfMemory: unable to allocate a module.
Example:
-- Without error handling
m = box.lib.load('path/to/library)
-- With error handling
m, err = pcall(box.lib.load, 'path/to/library')
if err ~= nil then
print(err)
end
module:unload() -> true | error
Unloads a module. Returns true on success, otherwise an error
is thrown. Once the module is unloaded one can't load new
functions from this module instance.
Possible errors:
- IllegalParams: a module is not supplied.
- IllegalParams: a module is already unloaded.
Example:
m = box.lib.load('path/to/library')
--
-- do something with module
--
m:unload()
If there are functions from this module referenced somewhere
in other places of Lua code they still can be executed because
the module continue sitting in memory until the last reference
to it is closed.
If the module become a target to the Lua's garbage collector
then unload is called implicitly.
module:load(name) -> obj | error
Loads a new function with name name from the previously
loaded module and return a callable object instance
associated with the function. On failure an error is thrown.
Possible errors:
- IllegalParams: function name is either not supplied
or not a string. - IllegalParams: attempt to load a function but module
has been unloaded already. - ClientError: no such function in the module.
- OutOfMemory: unable to allocate a function.
Example:
-- Load a module if not been loaded yet.
m = box.lib.load('path/to/library')
-- Load a function with the `foo` name from the module `m`.
func = m:load('foo')
In case if there is no need for further loading of other
functions from the same module then the module might be
unloaded immediately.
m = box.lib.load('path/to/library')
func = m:load('foo')
m:unload()
function:unload() -> true | error
Unloads a function. Returns true on success, otherwise
an error is thrown.
Possible errors:
- IllegalParams: function name is either not supplied
or not a string. - IllegalParams: the function already unloaded.
Example:
m = box.lib.load('path/to/library')
func = m:load('foo')
--
-- do something with function and cleanup then
--
func:unload()
m:unload()
If the function become a target to the Lua's garbage collector
then unload is called implicitly.
Executing a loaded function
Once function is loaded it can be executed as an ordinary Lua call.
Lets consider the following example. We have a C function which
takes two numbers and returns their sum.
int
cfunc_sum(box_function_ctx_t *ctx, const char *args, const char *args_end)
{
uint32_t arg_count = mp_decode_array(&args);
if (arg_count != 2) {
return box_error_set(__FILE__, __LINE__, ER_PROC_C, "%s",
"invalid argument count");
}
uint64_t a = mp_decode_uint(&args);
uint64_t b = mp_decode_uint(&args);
char res[16];
char *end = mp_encode_uint(res, a + b);
box_return_mp(ctx, res, end);
return 0;
}
The name of the function is cfunc_sum and the function is built into
cfunc.so shared library.
First we should load it as
m = box.lib.load('cfunc')
cfunc_sum = m:load('cfunc_sum')
Once successfully loaded we can execute it. Lets call the
cfunc_sum with wrong number of arguments
cfunc_sum()
| ---
| - error: invalid argument count
We will see the "invalid argument count" message in output.
The error message has been set by the box_error_set in C
code above.
On success the sum of arguments will be printed out.
cfunc_sum(1, 2)
| ---
| - 3
The functions may return multiple results. For example a trivial
echo function which prints arguments passed in.
cfunc_echo(1,2,3)
| ---
| - 1
| - 2
| - 3
Module and function caches
Loading a module is relatively slow procedure because operating
system needs to read the library, resolve its symbols and etc.
Thus to speedup this procedure if the module is loaded for a first
time we put it into an internal cache. If module is sitting in
the cache already and new request to load comes in -- we simply
reuse a previous copy. In case if module is updated on a storage
device then on new load attempt we detect that file attributes
(such as device number, inode, size, modification time) get changed
and reload module from the scratch. Note that newly loaded module
does not intersect with previously loaded modules, the continue
operating with code previously read from cache.
Thus if there is a need to update a module then all module instances
should be unloaded (together with functions) and loaded again.
Similar caching technique applied to functions -- only first function
allocation cause symbol resolving, next ones are simply obtained from
a function cache.
Requested by @cyrillos in https://github.com/tarantool/tarantool/commit/f463b5fa1bfc19049d145e495ac4a5f2a3673590
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the box reference document linked as the root document and review its existing module-section structure. Add the supplied box.lib overview, API descriptions, C and Lua examples, and caching notes; done means the new section is integrated in the reference and its examples and links render correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, lua
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100