In a broad sense, Domus client applications are those that rely on the functionalities of the user-level library domus_libusr.py to operate the Domus abstractions (Domus clusters and Domus DHTs). For instance, the domus_manager_cluster.py and domus_manager_dht.py tools are examples of client applications, though special ones (of the administrative-kind), once they are usable as intermediates to Domus by other applications. Users, however, may be concerned with the development of their own Domus client applications, based on direct calls to the methods of domus_libusr.py, for performance and flexibility reasons.
The user-level library domus_libusr.py exports two classes:
- cDomusUsrProxy (i.e., cluster Domus User-level Proxy)
- dDomusUsrProxy (i.e., dht Domus User-level Proxy)
Basically, objects of these classes are proxies for peer objects that live in the process space of the Domus supervisor service.
The lifecicle of proxies of any of the above classes includes 3 different states:
- "new" : the object has been created, but is yet to be bound to a remote peer;
- "bound" : the object is bound to a remote peer;
- "unbound" : the object was unbound from its remote peer; once in the state "unbound", the object must be discarded, and a new object of the same kind must be created to pursue similar actions (that is, the object cannot be reused, although its name may be bound to another Python object)
Thus, there are only 2 valid transitions: 1) from state "new" to "bound", and 2) from state "bound" to "unbound". These transitions results from invoking different methods, depending on the object class - see 6.6 - cDomusUsrProxy Methods and 6.8 - dDomusUsrProxy Methods.
The current state of an object may always be known by inspecting its attribute _state. Also, the current state of an object imposes a specific subset of attributes that may be modified (WRITE access) or inspected (READ access) - see 6.5 - cDomusUsrProxy Attributes and 6.7 - dDomusUsrProxy Attributes.
Proxy objects support several types of public (user-level) attributes:
- LOCAL: attributes that live only on the client-side, that is, they only exist in the proxy object and are never exported to its remote peer (supervisor-side); access mode may be READ-only or READ-WRITE, depending on the state of the proxy;
- REMOTE EXTERNAL: attributes of the remote peer that may be defined, in first place, at the client-side and then exported to the supervisor-side; prior to the export, READ-WRITE access is supported; after the export (remote definition), just READ-only access is supported;
- REMOTE INTERNAL: attributes of the remote peer defined internally at the supervisor-side and which may be later imported from the client-side for inspection; thus, just READ-only access is supported;
After the instantiation of a proxy, its attributes should be (re)defined or retrieved by using only specific methods of the proxy class (cdomus_attset and cdomus_attget for the cDomusUsrProxy class, and dht_attset and dht_attget for the dDomusUsrProxy class). Direct access to attributes using Python built-in dictionary methods should not be used, once such does not ensure additional validations and operations that are necessary.
All public methods of the cDomusUsrProxy and dDomusUsrProxy classes return a Pyhton list (ret1,ret2). The items of the list have the following meaning:
- ret1 is an integer whose value conveys success (zero value) or failure (positive value);
- on success, ret2 may simply be None or it may hold additional results from the operation;
- on failure, ret1 is one of the positive error codes defined in the domus_libsys.py library, such that domus_libsys.STRERROR[ret1] returns an appropriate error string; in the same circumstances, ret2 may simply be None or it may be a secondary positive error code, allowing for a more in-depth understanding of the failure via the secondary error string domus_libsys.STRERROR[ret2];
The cDomusUsrProxy class supports the following public attributes:
LOCAL attributes:
-
_state : current state of the object ("new", "bound" or "unbound"); value type: string; access mode: READ-only, on any state;
-
_debug : debug status (0 => off, 1=> on); effective only if --debug was supplied during the installation process; value type: integer; default value: 0; access mode: READ-WRITE on "new" and "bound" states;
REMOTE EXTERNAL attributes:
-
_cluster_name : the name of the Domus cluster to be managed (the name must be unique, among the Domus clusters deployed by the same user); the value of this attribute must be supplied to the constructor, but may be modified during the "new" state; value type: string;
-
_supervisor_interface : DNS name or IP address of a network interface of a cluster node selected to run the supervisor service (usually the ROCKS frontend node); the value of this attribute must be supplied to the constructor, but may be modified during the "new" state; value type: string;
-
_supervisor_port : TCP/IP port of the supervisor service; the value of this attribute must be supplied to the constructor, but may be modified during the "new" state; value type: integer;
-
_cluster_conf_file_path : path to the Domus cluster configuration file; for a Domus cluster named cluster_name the file is expected to be ~user/.domus/etc/domus#cluster_name#conf, but an alternate file name may be given; the value of this attribute may or may not be supplied to the constructor; in either case, it may be modified during the "new" state; if none file is supplied, the parameters that would be defined via the file will be given default values defined in domus_libsys.py; value type: string;
For all REMOTE EXTERNAL attributes, access mode is READ-WRITE on "new" state and READ-only on "bound" state.
REMOTE INTERNAL attributes:
-
_dhts : the set of DHTs currently supported by the Domus cluster; value type: structured;
-
_interfaces : the set of network interfaces currently known to the Domus cluster supervisor; value type: structured;
-
_nodes : the set of (physical) cluster nodes currently known to the Domus cluster supervisor; value type: structured;
-
_services : the set of Domus regular services currently known to the Domus cluster supervisor; value type: structured;
For all REMOTE INTERNAL attributes, access mode is READ-only on the "bound" state.
The cDomusUsrProxy class supports the following public methods:
Constructor:
-
cDomusUsrProxy(cluster_name, supervisor_interface, supervisor_port, cluster_conf_file_path) : the constructor parameters are used to valuate the REMOTE EXTERNAL attributes of the class, as defined above;
Management of Domus Clusters:
-
cdomus_ping() : check if the Domus cluster referenced by the proxy is active (that is, if its supervisor and regular services are running); proxy state: any, and does not change;
-
cdomus_open() : bind the proxy to an active Domus cluster; proxy state: must be "new" and changes to "bound";
-
cdomus_close() : unbind the proxy from an active Domus cluster; proxy state: must be "bound" and changes to "unbound";
-
cdomus_create() : create the Domus cluster (which becomes active) referenced by the proxy, by spawning the supervisor service; any REMOTE EXTERNAL attributes possibly defined while the proxy was in the state "new" are exported to the supervisor; proxy state: must be "new" and changes to "bound";
-
cdomus_destroy() : destroy the Domus cluster referenced by the proxy (that is, terminate all the Domus services eventually running and remove their persistent state); the Domus cluster does not need to be active in order to be destroyed; to destroy a Domus cluster in the active state, the proxy must be in the state "bound"; to destroy a Domus cluster in the inactive state, the proxy must be in the state "new"; in both cases, the proxy state becomes "unbound";
-
cdomus_shutdown() : shutdown (deactivate) the Domus cluster referenced by the proxy (that is, ask all Domus services to save their state to disk, after which they terminate); the Domus cluster becomes inactive; proxy state: must be "bound" and changes to "unbound";
-
cdomus_restart() : restart (reactivate) the Domus cluster referenced by the proxy (that is, respawn all the Domus services and ask them to load their state from disk); the Domus cluster becomes active; proxy state: must be "new" and changes to "bound";
-
cdomus_attset(attname, attvalue) : set the attribute attname with the value attvalue (feasible only for attributes that support the WRITE access mode - see 6.5 - cDomusUsrProxy Attributes); proxy-state: "new" or "bound", and does not change;
-
cdomus_attget(attname) : get the value of the attribute attname (feasible only for attributes that support the READ access mode - see 6.5 - cDomusUsrProxy Attributes); proxy-state: any, and does not change; return value on success: (0,ret2), where ret2 is the value of the attribute (the value type will depend on the specific attribute that was queried);
For methods cdomus_ping to cdomus_attset, the return value on success is (0,None).
Management of Domus Services:
-
supervisor_ping() : check if the supervisor service (of the Domus cluster referenced by the proxy) is running; proxy state: must be "bound", and does not change;
-
service_ping(service_interface) : check if a regular service (of the Domus cluster referenced by the proxy) is running, bound to the network interface service_interface; proxy state: must be "bound", and does not change;
-
service_add(service_interface, service_port) : add (spawns) a regular service (to the Domus cluster referenced by the proxy), bound to the network interface service_interface and TCP/IP port service_port; proxy state: must be "bound", and does not change;
For all methods, the return value on success is (0,None).
LOCAL attributes:
-
_state : current state of the object ("new", "bound" or "unbound"); value type: string; access mode: READ-only, on any state;
-
_cdomus : proxy to the Domus cluster that hosts the DHT; value type: the name of an instance (a Python object) of the cDomusUsrProxy class; access mode: READ-only, on any state;
-
_protocol : message exchange protocol to be used for dictionary record operations (put, del, get, ...); value type: string ("tcp" or "udp"); default value: "udp"; access mode: READ-WRITE on "new" and "bound" states;
-
_lookup_direct_status : status ("on" => active; "off" => inactive) of the direct lookup method (see 6.10 - Lookup Methods); value type: string; default value: "on"; access mode: READ-WRITE on "bound" state;
-
_lookup_cached_status : status ("on" => active; "off" => inactive) of the cached lookup method (see 6.10 - Lookup Methods); value type: string; default value: "on"; access mode: READ-WRITE on "bound" state;
REMOTE EXTERNAL attributes:
-
_dht_name : name of the DHT to be managed (the name must be unique, among the DHTs deployed by the same user); the value of this attribute must be supplied to the constructor, but may be modified during the "new" state; value type: string;
-
_onv : overall number of vnodes of the DHT; conveys the level of potential parallelism (in the number of cluster nodes) in the realization of the DHT; value type: integer;
-
_mnpv : minimum number of partitions/hashes per vnode of the DHT; an indirect way to configure the quality of the distribution of the DHT hashes among Domus services; the bigger the value of the attribute, the better will be the quality (i.e., the accuracy of the distribution); value type: integer, but restricted to powers of 2;
-
_mnrs : minimum number of routing services of the DHT; a way to enforce a minimum level of effective parallelism in the support of the routing tasks of the DHT; value type: integer;
-
_msrs : maximum set of routing services of the DHT; the routing superset of the DHT (=> routing services for the DHT must be chosen from this set); also, an indirect way to enforce a maximum level of effective parallelism in the support of the routing tasks of the DHT; value type: a Python sequence of DNS names or IP addresses, like ("compute-1-0", "compute-1-1"); the default is the special value ("all",) which conveys all the known Domus services; access mode: READ-WRITE on "new" state and READ-only on "bound" state;
-
_mnss : minimum number of storage services of the DHT; a way to enforce a minimum level of effective parallelism in the support of the storage tasks of the DHT; value type: integer;
-
_msss : maximum set of storage services of the DHT; the storage superset of the DHT (=> storage services for the DHT must be chosen from this set); also, an indirect way to enforce a maximum level of effective parallelism in the support of the storage tasks of the DHT; value type: a Python sequence of DNS names or IP addresses, like ("compute-1-0", "compute-1-1"); the default is the special value ("all",) which conveys all the known Domus services;
-
_sm : storage medium ("ram" or "disk") of the DHT (see 6.9 - Storage Technologies); value type: string; default value: "ram";
-
_sp : storage platform ("python-dict", "python-cdb", "python-bsddb-hash", "python-bsddb-btree", "libchord-bsddb-hash", "libchord-bsddb-btree") of the DHT (see 6.9 - Storage Technologies); value type: string; default value: "python-dict";
-
_mssv : maximum storage per storage vnode of the DHT; in conjunction with the initial value of _onv (see above) allows the creation of a DHT only if there is enough free storage available; value type: integer (Mbytes); default value: 32 (Mbytes);
For all REMOTE EXTERNAL attributes (except _dht_name), access mode is READ-WRITE on "new" state and READ-only on "bound" state.
Some of the previous attributes are based on the concept o vnode; vnodes are coarse-grain units of measurement of the enrollment level of each Domus services (or, equivalently, of the respective cluster nodes) in Domus DHTs; for detailed information about the vnode concept, see ?? [TODO].
Not all combinations of _sm and _sp attributes are valid; also, some dictionary operations (put, get, del, ...) may not be supported (or may be partially supported) by certain combinations - see 6.9 - Storage Technologies for details.
REMOTE INTERNAL attributes:
-
_onp : "overall number of partitions/hashes" of the DHT; value type: integer;
-
_rdt : "routing distribution table"; shows how the routing tasks of the DHT are supported by the Domus services of; value type: structured;
-
_sdt : "storage distribution table"; shows how the storage tasks of the DHT are supported by the Domus services of; value type: structured;
-
_records_stats : "records statistics"; a tuple with several statistics about the user records population of the DHT; the 1st item gives the overall number of records; the 2nd item is the accumulated size (in bytes) of all records; the 3rd item provides specific information for each DHT service; thus, the 3rd item is again a tuple, where each element follows the scheme ( (IP address, IP port), number of records, size of records ) ; value type: structured;
For all REMOTE INTERNAL attributes, access mode is READ-only on the "bound" state.
The dDomusUsrProxy class supports the following public methods:
Constructor:
-
dDomusUsrProxy(dht_name, cdomus) : dht_name is the unique name of the DHT; cdomus is a proxy for the Domus cluster that will host the DHT; the constructor parameters are used to valuate the DHT attributes _dht_name and _cdomus (see 6.7 - dDomusUsrProxy Attributes;
Management of Domus DHTs:
-
dht_ping() : check if the DHT referenced by the proxy is online; proxy state: any, and does not change;
-
dht_probe() : check if the DHT referenced by the proxy belongs to the Domus cluster referenced by the DHT attribute _cdomus (independently of the online/offline state of the DHT); proxy state: any, and does not change;
-
dht_open() : bind the proxy to an online DHT; proxy state: must be "new" and changes to "bound";
-
dht_close() : unbind the proxy from an online DHT; proxy state: must be "bound" and changes to "unbound";
-
dht_create() : create the DHT (which becomes online) referenced by the proxy; any REMOTE EXTERNAL attributes possibly defined while the proxy was in the state "new" are exported to the supervisor; proxy state: must be "new" and changes to "bound";
-
dht_destroy() : destroy the DHT referenced by the proxy (that is, Domus services will remove all DHT related state and data); the DHT does not need to be online in order to be destroyed (but its hosting Domus cluster must be active); to destroy a DHT in the online state, the proxy must be in the state "bound"; to destroy a DHT in the offline state, the proxy must be in the state "new"; in both cases, the proxy state becomes "unbound";
-
dht_shutdown() : shutdown (bring offline) the DHT referenced by the proxy (that is, ask all Domus services to save to disk all state and data related to the DHT (the saving is done under the directory specified by the DOMUS_SERVICE_ROOT_DIR_PATH parameter of the Domus cluster configuration file); the DHT enters the offline state, where data records are inaccessible, until the DHT is brought again to the online state; proxy state: must be "bound" and changes to "unbound";
-
dht_restart() : restart (bring online) the DHT referenced by the proxy (that is, if the DHT is offline, its state will be recovered from disk and dictionary operations on the DHT become possible); proxy state: must be "new" and changes to "bound";
-
dht_attset(attname, attvalue) : set the attribute attname with the value attvalue (feasible only for attributes that support the WRITE access mode - see 6.7 - dDomusUsrProxy Attributes); proxy-state: "new" or "bound", and does not change;
-
dht_attget(attname) : get the value of the attribute attname (feasible only for attributes that support the READ access mode - see 6.7 - dDomusUsrProxy Attributes); proxy-state: any, and does not change; return value on success: (0,ret2), where ret2 is the value of the attribute (the value type will depend on the specific attribute that was queried);
For methods dht_ping to dht_attset, the return value on success is (0,None).
Dictionary Operations:
-
dht_record_probe(key) : checks if a data record indexed by key exists in the DHT;
-
dht_record_put(key, data) : inserts (if necessary, overwrites) the data record <key, data> in the DHT;
-
dht_record_get(key) : get the data component of a possible DHT record indexed by key; return value on success: (0,ret2), where ret2 is the data component;
-
dht_record_del(key) : removes a possible DHT record indexed by key;
-
dht_record_pop(rounds) : get and remove a random record <key, data> from the DHT, limited to maximum number of rounds, where each round is a random walk of the DHT services; the default number of rounds is 1, which may not be sufficient if many insertions and deletions are taking place concurrently;
key and data may be any pickable (i.e., serializable) Python objects (as such, Domus DHTs are dictionaries of generic data). Except for the methods dht_record_get and dht_record_pop, the return value on success is (0,None). For all Dictionary Operations, the DHT proxy state must be "bound", and does not change.
Lookup Operations:
-
dht_record_lookup(key [, method]) : lookup a possible DHT record indexed by key, starting the discovery with a certain lookup method (see 6.10 - Lookup Methods); return value on success: (0,ret2) where ret2=(hash, routing service, storage service, hop count);
-
dht_lookup(hash [, method]) : lookup the hash hash, starting the discovery with a certain lookup method (see 6.10 - Lookup Methods); return value on success: (0,ret2) where ret2=(routing service, storage service, hop count);
For all Lookup Operations: 1) the method parameter is optional (the "direct" method is assumed by default);
2) the valid values for method depend on the current value of the DHT attributes _lookup_direct_status and _lookup_cached_status (see 6.10 - Lookup Methods for details); 3) the "hop count" in the return list is the number of network hops that were necessary to resolve the lookup; 4) the DHT proxy state must be "bound", and does not change.
In Domus, a storage technology is defined by a pair <storage platform , storage medium>, selectable on a per DHT basis. The selection is done by means of the DHT attributes _sp and _sm, respectively (see 6.7 - dDomusUsrProxy Attributes).
A storage platform refers to a particular dictionary implementation. Depending on the data persistence requirements of client applications, the storage medium may be set to "ram" or "disk".
The following is a partial list of the storage technologies currently supported by Domus (only the most performant technologies are considered here):
- <"python-dict","ram"> : Python built-in dictionary, on RAM; it is the fastest non-persistent dictionary implementation in Domus;
- <"python-cdb","disk"> : constant database, on DISK, accessed via the Python module cdb; it is the fastest persistent dictionary implementation in Domus; however, it must be used in a Write-once-Read-many fashion (initially, only insertions are allowed; then, after the insertion of the pair < key,data > = < None,None >, only retrievals are possible; removals are never possible);
- <"domus-bsddb-btree","ram"/"disk"> , <"domus-bsddb-hash","ram"/"disk"> : BerkeleyDB dictionaries, based on B+Trees or Dynamic Hash Tables, and operated on RAM or DISK; the dictionaries are not accessed via the Python module bsddb; instead, an external C-crafted module keeps a Red-Black-Tree of BerkeleyDB dictionaries that allows for a faster access when compared to the usage of the bsddb module;
The technologies above are ordered from the fastest to the slowest ones (top to bottom, an left to right). In a complementary perspective, their classification in terms of average storage overhead (measured on disk, when DHTs are offline) is also given:
- <"python-dict","ram"> : 75%
- <"domus-bsddb-hash","ram"/"disk"> : 275% / 250%
- <"domus-bsddb-btree","ram"/"disk"> : 300% / 400%
- <"python-cdb","disk"> : 400%
The knowledge of their relative performance and storage overhead helps to select the best technology for a certain scenario.
In a DHT, access to a < key, data > record always involves a lookup operation to find the (putative) service/node responsible for the storage of the record. In Domus, the lookup process may exploit several lookup methods, in the scope of a lookup strategy.
Domus implements three lookup methods: "direct" (D), "cached" (C) and "random" (R). A lookup strategy is then a sequence of lookup methods; a lookup starts with the 1st method of the sequence; an automatic fallout takes place from the current method to the next one in the sequence if the current method translates into a lookup miss. The valid lookup strategies are: < D,R >, < D,C,R >, < C,R > and < R >. These strategies allow a gracious decay in performance, from more error-prone (but faster) methods, to more accurate (but slower) methods.
The rational behind each lookup method is as follows:
- "direct" method: during the creation of a DHT, the supervisor service performs a (weighted) distribution of the DHT hashes, among a set of regular services; this initial distribution follows a simple, deterministic algorithm, such that the only information that is needed to reconstruct that distribution is the number of hashes assigned to each service; later, when a client application opens/creates/restarts a DHT, the supervisor is asked that information which, thereafter, will be used to resolve any lookup request; if the DHT has not yet been redistributed since its creation, then a 100% hit-ratio will be achieved; if the DHT has been somehow redistributed, lookup-misses will accumulate and, past a certain threshold (50%, by default), the "direct" method will be turned off;
- "cached" method: it consists on distributed lookup (based on Chord - see ??), enriched with a client-side LRU cache, per DHT; the cache is feed by distributed lookup results; initially, the cache is empty and the random method (see bellow) is necessary to initialize it; the cache contents will then be used to perform accelerated routing (discovery of topological shortcuts: cache records are used in order to define a starting service for a distributed lookup chain, as close as possible (in a Chord graph) to the end of the chain; the same rationale is used along the lookup chain, when a routing service inspects many local routing tables in order to make a routing decision); lookup-misses from the cached method trigger an automatic fallout to the random method and an update of the cache with its results;
- "random" method: the random method operates on minimal information about the current distribution of the DHT; basically, it needs to know only the number of hashes (and not which hashes) assigned to each of the services that support the DHT; the amount of such information is small, when compared to a full mapping of hashes to services; in order to define the starting service for a distributed lookup chain, a weighted random choice is sufficient, among the services that support the DHT (the choice is weighted by the number of hashes assigned to each service).
By default, the "direct" and the "cached" methods are active when a DHT proxy is created, but those methods can be deactivated/reactivated as convenient, through the attributes _lookup_direct_status and _lookup_cached_status, on a per DHT basis (see 6.7 dDomusUsrProxy Attributes). In turn, the "random" method is always on: it cannot be turned off once it is the last lookup resort (this explains why every valid routing strategy always includes the random method, as seen above).
Any one of the valid routing strategies may thus be enforced by properly tuning the _lookup_direct_status and _lookup_cached_status DHT attributes. Moreover, for the DHT methods dht_record_lookup and dht_lookup (see 6.8 dDomusUsrProxy Methods), the current strategy may be further refined by choosing a possibly different starting lookup method (using the parameter method of those DHT methods), provided it is part of the current routing strategy (for instance, if the current strategy is < D,C,R >, then one could refine it by starting with the "cached" (C) method, instead of the (default) "direct" (D) method).
Client applications may be developed by following a simple strategy:
- To operate a Domus cluster, create a "Domus cluster proxy object", like the _CDOMUS_USRPROXY Python object bellow:
_CDOMUS_USRPROXY = domus_libusr.cDomusUsrProxy(cluster_name="mycluster",\
supervisor_interface="192.168.0.1",\
supervisor_port= 7571,
cluster_conf_file_path="/home/user/.domus/etc/domus#mycluster#conf")
After its instantiation, the _CDOMUS_USRPROXY object is in the state "new".
-
Bind the _CDOMUS_USRPROXY object to the Domus cluster, after which the _CDOMUS_USRPROXY object enters the state "bound"; the binding results from the methods cdomus_open, cdomus_create or cdomus_restart of the cDomusUsrProxy class; unbinding results from the methods cdomus_close, cdomus_destroy or cdomus_shutdown; once in the state "unbound", _CDOMUS_USRPROXY must become a reference to a new cDomusUsrProxy object in order to be again usable.
- To operate a Domus DHT, create a "Domus DHT proxy object", like the _DDOMUS_USRPROXY Python object bellow, providing it a reference to a "Domus cluster proxy object" already in the "bound" state (like the _CDOMUS_USRPROXY object from above):
_DDOMUS_USRPROXY = domus_libusr.dDomusUsrProxy( dht_name = "myDhtDomus", \
cdomus = _CDOMUS_USRPROXY)
After its instantiation, the _DDOMUS_USRPROXY object is in the state "new".
-
Bind the _DDOMUS_USRPROXY object to the DHT, after which the _DDOMUS_USRPROXY object enters the state "bound"; the binding results from the methods dht_open, dht_create or dht_restart of the cDomusUsrProxy class; unbinding results from the methods dht_close, dht_destroy or dht_shutdown; once in the state "unbound", _DDOMUS_USRPROXY must become a reference to a new dDomusUsrProxy object in order to be again usable.
- a "Domus cluster proxy object", like _CDOMUS_USRPROXY, is shareable by multiple "Domus DHT proxy objects", like _DDOMUS_USRPROXY; if such is intended, it is recommended to activate threadsafe support on the installed files during the Domus installation process (see step 4.3 in 2.2 - Installation Instructions);
The current Domus version also includes support (experimental) for the development of client applications in the C programming language. Assuming ~domus/.domus was the target folder during Domus installation, the function prototypes for the C interface may be found in ~domus/.domus/include/domus_libusr_c.h, and examples of client applications in C are available at ~domus/.domus/examples.
Some important restrictions of the current C interface are:
- except for constructor functions, the return value of the C functions is always a string; for instance, a Python list (0,None) returned by the Python-side is received as the string "(0,None)" in the C-side; thus, further parsing of the string is necessary in order to extract all relevant data from it (the parsing task is currently left to the programmer of the client applications);
- the key and data parameters of the C versions of the dht_record_probe/put/del/get/lookup methods are assumed as C strings (null terminated); this means that any key and data whose primitive type is not a string must first be converted into a string (for instance, by using base64 serialization functions).
Assuming ~domus/.domus was the target folder during Domus installation, the contents of the folder ~domus/.domus/examples should be as shown next:
[domus@frontend]$ ls -la ~domus/.domus/examples
total 60
drwxr-xr-x 2 domus domus 4096 May 25 00:12 .
drwxr-xr-x 7 domus domus 4096 May 24 23:51 ..
-rw-r--r-- 1 domus domus 8275 May 24 23:51 domus_example_1.c
-rwxr-xr-x 1 domus domus 6343 May 24 23:56 domus_example_1.py
-rw-r--r-- 1 domus domus 12894 May 24 23:51 domus_example_2.c
-rwxr-xr-x 1 domus domus 9271 May 25 00:08 domus_example_2.py
-rwxr-xr-x 1 domus domus 645 May 24 23:51 domus_examples.makefile
The files domus_example_?.py illustrate the application of the previous Programming Methodology: domus_example_1.py concentrates on the cDomusUsrProxy class; domus_example_2.py expands and complements the 1st example, by focusing on the dDomusUsrProxy class.
The utilization of the experimental C interface is demonstrated by the files domus_example_1.c and domus_example_2.c, which are C versions of the Python examples. The executables may be generated by calling make -f domus_examples.makefile. The makefile domus_examples.makefile may be used as starting point to compile other client applications developed in C.
Prev | Top | Next