Drivers¶
Note
core.NS ZEN rule #4 - Drivers are the perfect technics to hide low-level logic from the high-level logic and organize communication between them via functons
What is the “low-level logic” and why drivers in core.NS ? Please allow me to give a simple definition of what is core.NS driver:
The core.NS driver is a element of the code, which besides the reference to the global namespace, having a reference to a context
Essentially, each driver it is a directory, holding some context-specific data as well as partial applied functions, each of them is with two bound arguments: one to a global namespace, another one is to a directory, keeping context. The closest “relative” of the core.NS drivers is a Unix drivers with contexts in /dev . There are low-level logic to work with, for exaple /dev/sda, /dev/sdb and so on. Each of this logics, is provided with context and without context are rather abstract.
Let me bring some example. We will extend a functionality of the core.NS with the counters. Context for counter driver implementation will be stored in /dev. Each counter shall have a unique name. Each named counter must have an easy to understand, namespace-based interface. For example, we can call function f(“/dev/counter/create”)() to create counter and f(“/dev/c/$countername/++”)() to increase the value of the counter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def _counter_open(ns, ctx, name):
c = nsGet(ns, "/dev/c/{}".format(name))
if c is not None:
return c
else:
c = nsMkdir(ns, "/dev/c/{}".format(name))
nsSet(ns, "/dev/c/{}/counter".format(name), 0)
nsSet(ns, "/dev/c/{}/++".format(name), partial(_counter_increase, ns, c))
return c
def _counter_increase(ns, ctx):
_path = ctx["__name__"]
c = "{}/counter".format(_path)
nsSet(ns, c, nsGet(ns, c) + 1)
return nsGet(ns, c)
|
Unlike in previous examples, in low-level implementations, I am recommending to use functions from corens.ns than V(). There are reasons for that. Function _counter_open() takes extra parameter - name. When we will know the name, first, we are checking if such name in /dev/c already exists. If not, we shall create directory, initialize default value for the counter and create context-sensitive partially-applied function ++
After that, wrap it in _tpl = {} section of the module that you are adding to your core.NS.
_tpl = {
'counters': {
'create': _counter_open,
}
}
And then use Mk() function to initialize driver in /dev tree as Mk(‘counters’)