SlideShare uma empresa Scribd logo
1 de 53
[object Object]
Thierry GAYET - January 2012
Introduction
Official web site :  http://code.google.com/p/abus/ A-Bus is a lightweight message bus system, a simple way for embedded applications to talk to one another, merely in professional world, but not restricted to.  The message bus is built on top of a one-to-one message passing JSON-RPC framework.  There's no daemon involved in the message bus. Got trapped in the past with a clumsy inter process communication bus?  No sane alternative to propose as a replacement for a stinky legacy middle-ware?  It's now time to stop the hurting and get your chance to escape the wheel of reincarnation. ,[object Object]
DBUS ABUS UNIX SOCKETS ,[object Object],GNU/Linux kernel GNU/Linux kernel DBUS DAEMON libdbus libdbus binary1 binary1 libdbus libdbus binary1 binary1
This documentation is free; you can redistribute it without any restrictions. The modification or derived work must retain copyright and list all authors. This documentation is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Licence :  http://www.gnu.org/licenses/lgpl.html ,[object Object]
Maillist :  https://accounts.google.com/ServiceLogin?service=groups2&passive=1209600&continue=http://groups.google.com/group/abus-discuss&followup=http://groups.google.com/group/abus-discuss Abus issues :  http://code.google.com/p/abus/issues/list?can=1&q=&colspec=ID+Type+Status+Priority+Milestone+Owner+Summary&cells=tiles ,[object Object]
Build the abus library from sources
Get the latest abus source code from the subversion repository : $ svn checkout http://abus.googlecode.com/svn/trunk/ abus-read-only Then go into the directory: $ cd abus-read-only If you want to test abus over json-rpc call (for web purpose), you will need this package : $ sudo apt-get install libfcgi-dev  ,[object Object]
Abus support unitary test based on the google/test framework. You can install it on native GNU/linux such as :  $ sudo apt-get install libgtest-dev However, the google/test ”suck” with its autotools support, that's why we need to add a gtest.pc file in the following path : /usr/lib/pkgconfig/ with the following content : prefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: gtest Description: The google test framework Requires:  Version: 1.6.0 Libs: -lgtest -L${libdir} Cflags: -I${includedir}/gtest/ This file add metadata for the abus package. ,[object Object]
First we need to generate the intermediate autotools templates :  $ autoreconf -i --force That will generate: a Makefile.in  from the Makefile.am template a configure script and abus_config.h.in from the configure.ac template This is possible to see the configure usage: ./configure --help Configure the abus package : $ ./configure –prefix=/usr --enable-fcgi --enable-examples –enable-test  Build it :  $ make -j 5 Install it :  $ sudo make install or $ sudo make install DESTDIR=<INSTALL_PATH> Check your package using google/test framework : $ make check ← Everything must be in  green  (not  red ) ,[object Object]
/usr/include/abus.hpp /usr/include/jsonrpc.h /usr/include/json.h /usr/include/abus.h /usr/include/standard.h /usr/include/hashtab.h Headers : /usr/lib/pkgconfig /usr/lib/pkgconfig/abus.pc /usr/lib/libabus.la /usr/lib/libabus.so.0 /usr/lib/libabus.so /usr/lib/libabus.a /usr/lib/libabus.so.0.0.0 Libraries & meta-data : /usr/share/man/man1/abus-send.1 Online documentation :  /usr/bin/abus-send Tools :  ,[object Object]
Abus & autotools integration
Abus is fully compatible with recent autotools. That provide the possibility to interract easily with the abus library such as : (extract from a configure.ac template) (…) dnl -------------------------------------------- dnl Test if the libabus is well available in the stagingdir dnl If so get the cflags and ldflag from the .pc file dnl -------------------------------------------- LIBABUS_REQUIRED_VERSION=0.2~svn PKG_CHECK_MODULES([ABUS],[abus >= $LIBABUS_REQUIRED_VERSION],[have_abus=yes],[have_abus=no]) if test &quot;$have_libabus&quot; = no ; then   AC_MSG_ERROR([Missing libgtest library $LIBABUS_REQUIRED_VERSION (http://code.google.com/p/abus/) !!]) Fi (…) The above set the abus library as mandatory dependency. ,[object Object]
(extract from a Makefile.am template) (...) bin_PROGRAMS  =  myBin myBin _SOURCES = $(top_srcdir)/src/myBin.c     $(top_srcdir)/src/myBin.h myBin _CFLAG  = -I$(HEADER_DIR)  $(ABUS_CFLAGS) or myBin _CPPGLAGS = $(ABUS_CPPFLAGS)  or myBin _CXXGLAGS = $(ABUS_CXXFLAGS)  myBin _LDFLAGS =  myBin _LDADD  = $(ABUS_LIBS) ,[object Object]
The abus public API Header : abus.h
const   char  * abus_get_version (); const   char  * abus_get_copyright (); Global : int   abus_init ( abus_t  *abus); int   abus_cleanup ( abus_t  *abus); Initialization and clean an abus context int   abus_decl_method ( abus_t  *abus,  const   char  *service_name,  const   char  *method_name,  abus_callback_t  method_callback,  int  flags,  void  *arg,  const   char  *descr,  const   char  *fmt,  const   char  *result_fmt); int   abus_undecl_method ( abus_t  *abus,  const   char  *service_name,  const   char  *method_name); Declare and undeclare a method : int   abus_request_method_init ( abus_t  *abus,  const   char  *service_name,  const   char  *method_name, json_rpc_t *json_rpc); int   abus_request_method_invoke ( abus_t  *abus, json_rpc_t *json_rpc,  int  flags,  int  timeout); int   abus_request_method_cleanup ( abus_t  *abus, json_rpc_t *json_rpc); Synchronous calls : int   abus_request_method_invoke_async ( abus_t  *abus, json_rpc_t *json_rpc,  int  timeout,  abus_callback_t  callback,  int  flags,  void  *arg); int   abus_request_method_wait_async ( abus_t  *abus, json_rpc_t *json_rpc,  int  timeout); Asynchronous calls with callback : typedef   void  (* abus_callback_t )(json_rpc_t *json_rpc,  void  *arg); ,[object Object]
int   abus_decl_event ( abus_t  *abus,  const   char  *service_name,  const   char  *event_name,  const   char  *descr,  const   char  *fmt); int   abus_undecl_event ( abus_t  *abus,  const   char  *service_name,  const   char  *event_name); int   abus_request_event_init ( abus_t  *abus,  const   char  *service_name,  const   char  *event_name, json_rpc_t *json_rpc); int   abus_request_event_publish ( abus_t  *abus, json_rpc_t *json_rpc,  int  flags); int   abus_request_event_cleanup ( abus_t  *abus, json_rpc_t *json_rpc); int   abus_event_subscribe ( abus_t  *abus,  const   char  *service_name,  const   char  *event_name,  abus_callback_t  callback,  int  flags,  void  *arg,  int  timeout); int   abus_event_unsubscribe ( abus_t  * abus ,  const   char  *service_name,  const   char  *event_name,  abus_callback_t  callback,  void  *arg,  int  timeout); Publish and subscribe : int   abus_decl_attr_int ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  int  *val,  int  flags,  const   char  *descr); int   abus_decl_attr_bool ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  bool  *val,  int  flags,  const   char  *descr); int   abus_decl_attr_double ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  double  *val,  int  flags,  const   char  *descr); int   abus_decl_attr_str ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  char  *val, size_t n,  int  flags,  const   char  *descr); int   abus_undecl_attr ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name); int   abus_attr_changed ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name); int   abus_append_attr ( abus_t  *abus, json_rpc_t *json_rpc,  const   char  *service_name,  const   char  *attr_name); Attributes/data model service side : int   abus_attr_get_int ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  int  *val,  int  timeout); int   abus_attr_get_bool ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  bool  *val,  int  timeout); int   abus_attr_get_double ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  double  *val,  int  timeout); int   abus_attr_get_str ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  char  *val, size_t n,  int  timeout); Attributes/data model client side : ,[object Object]
int   abus_attr_set_int ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  int  val,  int  timeout); int   abus_attr_set_bool ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  bool  val,  int  timeout); int   abus_attr_set_double ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  double  val,  int  timeout); int   abus_attr_set_str ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  const   char  *val,  int  timeout); int   abus_attr_subscribe_onchange ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  abus_callback_t  callback,  int  flags,  void  *arg,  int  timeout); int   abus_attr_unsubscribe_onchange ( abus_t  *abus,  const   char  *service_name,  const   char  *attr_name,  abus_callback_t  callback,  void  *arg,  int  timeout); int   abus_forward_rpc ( abus_t  *abus,  char  *buffer,  int  *buflen,  int  flags,  int  timeout); Fast/CGI helper : Latest API available here :  http://abus.googlecode.com/svn/doc/HEAD/html/index.html ,[object Object]
The libjson public API Header : json.h
JSON WIKIPEDIA :  http://en.wikipedia.org/wiki/JSON JSON standard (RFC) : http://www.ietf.org/rfc/rfc4627 Validate a json file : http://jsonlint.com/ JSON beautifier : http://jsonformatter.bugz.fr/  JSON SCHEMA :  http://json-schema.org/ Official website :  http://www.json.org/ JSON, or  J ava S cript  O bject  N otation, is a lightweight text-based open standard designed for  human-readable  data interchange. It is derived from the  JavaScript  scripting language for representing simple  data structures  and  associative arrays , called objects. Despite its relationship to JavaScript, it is language-independent, with parsers available for most languages. The JSON format was originally specified by  Douglas Crockford , and is described in  RFC 4627 . The official  Internet media type  for JSON is application/json. The JSON filename extension is .json. The JSON format is often used for  serializing  and transmitting structured data over a network connection. It is used primarily to transmit data between a server and web application, serving as an alternative to  XML . ,[object Object]
{ &quot;firstName&quot;: &quot;John&quot;, &quot;lastName&quot; : &quot;Smith&quot;, &quot;age&quot;  : 25, &quot;address&quot;  : { &quot;streetAddress&quot;: &quot;21 2nd Street&quot;, &quot;city&quot;  : &quot;New York&quot;, &quot;state&quot;  : &quot;NY&quot;, &quot;postalCode&quot;  : &quot;10021&quot; }, &quot;phoneNumber&quot;: [ { &quot;type&quot;  : &quot;home&quot;, &quot;number&quot;: &quot;212 555-1234&quot; }, { &quot;type&quot;  : &quot;fax&quot;, &quot;number&quot;: &quot;646 555-4567&quot; } ] } Exemple of JSON :  ,[object Object]
[object Object]
[object Object]
Get the parent's node : Some function have been implemented to the libjson : json_dom_val_t *  json_config_open ( const   char * szJsonFilename); void   json_config_cleanup ( json_dom_val_t * element); json_dom_val_t *  json_config_lookup ( json_dom_val_t * element,  const   char * szDirectoryNane); int   json_config_get_int ( json_dom_val_t * element,  int * val); Extract a node content by type : int   json_config_get_bool ( json_dom_val_t * element,  bool * val); int   json_config_get_string ( json_dom_val_t * element,  char ** val); int   json_config_get_double ( json_dom_val_t * element,  double * val); Locate a node and extract its content by type : int   json_config_get_direct_int ( json_dom_val_t * root,  const   char * directoryName,  const   char * attributeName,  int * val); bool   json_config_get_direct_bool ( json_dom_val_t * root,  const   char * directoryName,  const   char * attributeName,  bool * val); int   json_config_get_direct_string ( json_dom_val_t * root,  const   char * directoryName,  const   char * attributeName,  char ** val); int   json_config_get_direct_double ( json_dom_val_t * root,  const   char * directoryName,  const   char * attributeName,  double * val); ,[object Object]
int  main( int  argc,  char * argv[],  char * env[]) { int   ret = -1; char *   valItem  = NULL; char * valItem2 = NULL; char * valItem3 = NULL; json_dom_val_t* json_dom  = NULL; json_dom_val_t* myParentItem = NULL; json_dom_val_t* myItem = NULL; /* Load and parse the  json  file */ if  (argc >=2) { if  ( NULL != (json_dom = json_config_open(argv[1]))) { printf( &quot; [DBG] JSON  init  and converted into a DOM : OK &quot; ); printf( &quot; [DBG] Looking for the parent item ('result') . . .&quot; ); /* --------------------------------------------------------- */ /* First example  */ /* --------------------------------------------------------- */ if  (NULL != (myParentItem = json_config_lookup(json_dom,  &quot;networking&quot; ))) { printf( &quot; [DBG] Parent item 'networking' (%p) well found&quot; , myParentItem); if  (NULL != (myItem = json_config_lookup(myParentItem,  &quot; ipaddress &quot; ))) { printf( &quot; [DBG] Child item ' ipaddress ' (%p) well found &quot; , myItem); if  (-1 != (ret = json_config_get_string(myItem, &valItem))) printf( &quot; [DBG] Item's value = '%s' &quot; , valItem); else printf( &quot; [ERROR] Problem to get the item's value &quot; ); }  else  { printf( &quot; [ERROR] Child item not found &quot; ); }  /* IF */ ,[object Object]
if  (NULL != (myItem = json_config_lookup(myParentItem,  &quot;gateway&quot; ))) { printf( &quot; [DBG] Child item 'gateway' (%p) well found &quot; , myItem); if  (-1 != (ret = json_config_get_string(myItem, &valItem2))) printf( &quot; [DBG] Item's value = '%s' &quot; , valItem2); else printf( &quot; [ERROR] Problem to get the item's value &quot; ); }  else  { printf( &quot; [ERROR] Child item not found &quot; ); }  /* IF */ }  else  { printf( &quot; [ERROR] Parent item not found &quot; ); }  /* IF */ /* --------------------------------------------------------- */ /* Second example  */ /* --------------------------------------------------------- */ json_config_get_direct_string(json_dom,  &quot;networking&quot; ,  &quot; ipaddress &quot; , &valItem3); printf( &quot; [DBG] Item's value = '%s' &quot; , valItem3); /* Cleaning the  dom  */ if  (NULL != json_dom) json_config_cleanup(json_dom); }  else  { printf( &quot; [ERROR] JSON  init  and converted into a DOM : NOK &quot; ); }  /* IF */ printf( &quot;&quot; ); }  else  { printf( &quot; [ERROR] Expected parameter to %s !!&quot; , argv[0]); printf( &quot; [ERROR] Usage: %s <json file> &quot; , argv[0]); }  /* IF */ return (ret); } ,[object Object]
Roadmap : - extension with datamodel request ,[object Object]
local unix sockets First example : simple service and client libabus libabus libabus client service
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <errno.h> #include &quot;abus.h&quot; /* Main function */ int main(int argc, char **argv) {   /* Declare the abus context */ abus_t abus;   /* Initialize the abus context */ abus_init (&abus);   /* Register a first method */ abus_decl_method (&abus, &quot;examplesvc&quot;, &quot;sum&quot;, &svc_sum_cb, ABUS_RPC_FLAG_NONE, &quot;sumator cookie&quot;, &quot;Compute summation of two integers&quot;, &quot;a:i:first operand,b:i:second operand&quot;, &quot;res_value:i:summation&quot;);   /* Register another methode */ abus_decl_method (&abus, &quot;examplesvc&quot;, &quot;mult&quot;, &svc_mult_cb, ABUS_RPC_FLAG_NONE, &quot;multiply cookie&quot;, &quot;Compute multiplication of two integers&quot;, &quot;a:i:first operand,b:i:second operand&quot;, &quot;res_value:i:multiplication&quot;); /* do other stuff */ sleep(10000);   /* Clean the abus context – it unregister all methods */ abus_cleanup (&abus);   /* Exit the main function and provide a return code */ return EXIT_SUCCESS; } example-service.c ,[object Object]
static void  svc_sum_cb (json_rpc_t *json_rpc, void *arg) { int a, b; int ret; ret  =  json_rpc_get_int (json_rpc, &quot;a&quot;, &a); if (ret == 0) ret =  json_rpc_get_int (json_rpc, &quot;b&quot;, &b); printf(&quot;## %s: arg=%s, ret=%d, a=%d, b=%d, => result=%d&quot;, __func__, (const char*)arg, ret, a, b, a+b); if (ret) json_rpc_set_error (json_rpc, ret, NULL); else json_rpc_append_int (json_rpc, &quot;res_value&quot;, a+b); } static void  svc_mult_cb (json_rpc_t *json_rpc, void *arg) { int a, b; int ret; ret  =  json_rpc_get_int (json_rpc, &quot;a&quot;, &a); if (ret == 0) ret =  json_rpc_get_int (json_rpc, &quot;b&quot;, &b); printf(&quot;## %s: arg=%s, ret=%d, a=%d, b=%d, => result=%d&quot;, __func__, (const char*)arg, ret, a, b, a*b);   if (ret) json_rpc_set_error (json_rpc, ret, NULL); else json_rpc_append_int (json_rpc, &quot;res_value&quot;, a*b); } example-service.c ,[object Object]
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include &quot;abus.h&quot; #define RPC_TIMEOUT 1000 /* in ms */ int main(int argc, char **argv) { abus_t  abus; json_rpc_t json_rpc; int  ret;   Int  res_value; const char *service_name = &quot;examplesvc&quot;; if (argc < 4) { printf(&quot;usage: %s METHOD firstvalue secondvalue&quot;, argv[0]); exit(EXIT_FAILURE); } abus_init (&abus); /* method name is taken from command line */ ret =  abus_request_method_init (&abus, service_name, argv[1], &json_rpc); if (ret) exit(EXIT_FAILURE); /* pass 2 parameters: &quot;a&quot; and &quot;b&quot; */ json_rpc_append_int (&json_rpc, &quot;a&quot;, atoi(argv[2])); json_rpc_append_int (&json_rpc, &quot;b&quot;, atoi(argv[3])); example-client.c ,[object Object]
ret =  abus_request_method_invoke (&abus, &json_rpc, ABUS_RPC_FLAG_NONE, RPC_TIMEOUT); if (ret != 0) { printf(&quot;RPC failed with error %d&quot;, ret); exit(EXIT_FAILURE); } ret =  json_rpc_get_int (&json_rpc, &quot;res_value&quot;, &res_value); if (ret == 0) printf(&quot;res_value=%d&quot;, res_value); else printf(&quot;No result? error %d&quot;, ret); abus_request_method_cleanup (&abus, &json_rpc); abus_cleanup (&abus); return EXIT_SUCCESS; } example-client.c ,[object Object]
local unix sockets Second example : working with array libabus libabus libabus client service
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <errno.h> #include &quot;abus.h&quot; static void svc_array_sqr_cb(json_rpc_t *json_rpc, void *arg) { int k, a; int ret, count, i; int *ary = NULL; ret =  json_rpc_get_int (json_rpc, &quot;k&quot;, &k); if (ret != 0) { json_rpc_set_error (json_rpc, ret, NULL); return; } count =  json_rpc_get_array_count (json_rpc, &quot;my_array&quot;); if (count >= 0) { /* first put all the values in an array, in order to not mix json_rpc_get's and json_rpc_append's for readability sake */ ary = malloc(count*sizeof(int)); for (i = 0; i<count; i++) { /* Aim at i-th element within array &quot;my_array&quot; */ ret =  json_rpc_get_point_at (json_rpc, &quot;my_array&quot;, i); if (ret != 0) break; /* from that dictionary, get parameter &quot;a&quot; * Rem: expects all array elements to contain at least a param &quot;a&quot; */ ret =  json_rpc_get_int (json_rpc, &quot;a&quot;, &ary[i]); if (ret != 0) break; } } example-svc-array.c ,[object Object]
printf(&quot;## %s: arg=%s, ret=%d, k=%d, array count=%d&quot;, __func__, (const char*)arg, ret, k, count); if (ret) { json_rpc_set_error (json_rpc, ret, NULL); } else { json_rpc_append_int (json_rpc, &quot;res_k&quot;, k); /* begin the array */ json_rpc_append_args (json_rpc, JSON_KEY, &quot;res_array&quot;, -1, JSON_ARRAY_BEGIN, -1); for (i = 0; i<count; i++) { /* each array element *must* be an &quot;OBJECT&quot;, i.e. a dictonary */ json_rpc_append_args (json_rpc, JSON_OBJECT_BEGIN, -1); json_rpc_append_int (json_rpc, &quot;res_a&quot;, ary[i]*ary[i]); /* more stuff may be appended in there */ json_rpc_append_args (json_rpc, JSON_OBJECT_END, -1); } /* end the array */ json_rpc_append_args (json_rpc, JSON_ARRAY_END, -1); } if (ary) free(ary); } example-svc-array.c ,[object Object]
int main(int argc, char **argv) { abus_t abus; abus_init (&abus); abus_decl_method (&abus, &quot;examplearraysvc&quot;, &quot;sqr&quot;, &svc_array_sqr_cb, ABUS_RPC_FLAG_NONE, &quot;square cookie&quot;, &quot;Compute square value of all the elements of an array. Serves as an example of how to deal with array in A-Bus&quot;, &quot;k:i:some contant,my_array:(a:i:value to be squared,arg_index:i:index of arg for demo):array of stuff&quot;, &quot;res_k:i:same contant,res_array:(res_a:i:squared value):array of squared stuff&quot;); /* do other stuff */ sleep(10000); abus_cleanup (&abus); return EXIT_SUCCESS; } example-svc-array.c ,[object Object]
example-clnt-array.c #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include &quot;abus.h&quot; #define RPC_TIMEOUT 1000 /* ms */ int main(int argc, char **argv) { abus_t abus; json_rpc_t json_rpc; int count, i, ret, res_value; const char *service_name = &quot;examplearraysvc&quot;; if (argc < 4) { printf(&quot;usage: %s METHOD k values...&quot;, argv[0]); exit(EXIT_FAILURE); } abus_init (&abus); /* method name is taken from command line */ ret =  abus_request_method_init (&abus, service_name, argv[1], &json_rpc); if (ret) exit(EXIT_FAILURE); /* pass 2 parameters: &quot;k&quot; and &quot;my_array&quot; */ json_rpc_append_int (&json_rpc, &quot;k&quot;, atoi(argv[2])); /* begin the array */ json_rpc_append_args (&json_rpc, JSON_KEY, &quot;my_array&quot;, -1, JSON_ARRAY_BEGIN, -1); ,[object Object]
example-clnt-array.c   ret =  abus_request_method_invoke (&abus, &json_rpc, ABUS_RPC_FLAG_NONE, RPC_TIMEOUT); if (ret != 0) { printf(&quot;RPC failed with error %d&quot;, ret); exit(EXIT_FAILURE); } count =  json_rpc_get_array_count (&json_rpc, &quot;res_array&quot;); if (count < 0) { printf(&quot;No result? error %d&quot;, count); exit(EXIT_FAILURE); } ret =  json_rpc_get_int (&json_rpc, &quot;res_k&quot;, &res_value); if (ret == 0) printf(&quot;res_k=%d&quot;, res_value); else printf(&quot;No result? error %d&quot;, ret); for (i = 0; i<count; i++)  { /* Aim at i-th element within array &quot;res_array&quot; */ json_rpc_get_point_at (&json_rpc, &quot;res_array&quot;, i); printf(&quot;res_array[%d]&quot;, i); ret =  json_rpc_get_int (&json_rpc, &quot;res_a&quot;, &res_value); if (ret == 0) printf(&quot;res_a=%d&quot;, res_value); else printf(&quot;No result? error %d&quot;, ret); } ,[object Object]
example-clnt-array.c /* Aim back out of array */ json_rpc_get_point_at (&json_rpc, NULL, i); ret =  json_rpc_get_int (&json_rpc, &quot;res_k&quot;, &res_value); if (ret == 0) printf(&quot;res_k=%d (should be the same as previously)&quot;, res_value); else printf(&quot;No result? error %d&quot;, ret);   abus_request_method_cleanup (&abus, &json_rpc); abus_cleanup (&abus); return EXIT_SUCCESS; } ,[object Object]
local unix sockets Third example : exporting objects  libabus libabus libabus client service
This example is a service named &quot;exampleattrsvc&quot; written in C, dealing with attributes in a data model. To be used with the client example-clnt-attr. You may also use the abus-send program to test it: abus-send exampleattrsvc.get tree.some_int abus-send exampleattrsvc.get tree. abus-send exampleattrsvc.set tree.some_int:i:128 abus-send exampleattrsvc.get &quot;&quot; Here is how to play with event emitted upon attribute change (one event every 5 seconds): abus-send exampleattrsvc.subscribe attr_changed%tree.auto_count ,[object Object]
example-svc-attr.c #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <errno.h> #include &quot;abus.h&quot; int main(int argc, char **argv) { abus_t abus; const char *servicename = &quot;exampleattrsvc&quot;; int i; int my_int = 42; int my_other_int = -2; int my_auto_count = 0; abus_init (&abus); abus_decl_attr_int (&abus, servicename, &quot;tree.some_int&quot;, &my_int, ABUS_RPC_FLAG_NONE, &quot;Some integer, for demo purpose&quot;); abus_decl_attr_int (&abus, servicename, &quot;tree.some_other_int&quot;, &my_other_int, ABUS_RPC_FLAG_NONE, &quot;Some other integer, still for demo purpose&quot;); abus_decl_attr_int (&abus, servicename, &quot;tree.auto_count&quot;, &my_auto_count, ABUS_RPC_FLAG_NONE, &quot;Counter incremented every 5 seconds&quot;); /* do other stuff */ for (i = 0; i < 1000; i++)  { sleep(5); my_auto_count++; /* trigger event notification */ abus_attr_changed (&abus, servicename, &quot;tree.auto_count&quot;); } abus_cleanup (&abus); return EXIT_SUCCESS; } ,[object Object]
example-clnt-attr.c #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include &quot;abus.h&quot; #define RPC_TIMEOUT 1000 /* ms */ int main(int argc, char **argv) { abus_t abus; json_rpc_t json_rpc; int ret; const char *service_name = &quot;exampleattrsvc&quot;; const char *attr_name; int my_int; if (argc < 2) { printf(&quot;usage: %s ATTR newintegervalue&quot;, argv[0]); printf(&quot;usage: ATTR: some_int|some_other_int&quot;, argv[0]); exit(EXIT_FAILURE); } abus_init (&abus); /* attr name is taken from command line */ attr_name = argv[1]; ret =  abus_attr_get_int (&abus, service_name, attr_name, &my_int, RPC_TIMEOUT); if (ret) { printf(&quot;RPC failed with error %d&quot;, ret); abus_cleanup (&abus); exit(EXIT_FAILURE); } ,[object Object]
example-clnt-attr.c printf(&quot;Previous value: %s=%d&quot;, attr_name, my_int); my_int = atoi(argv[2]); ret =  abus_attr_set_int (&abus, service_name, attr_name, my_int, RPC_TIMEOUT); if (ret) { printf(&quot;RPC failed with error %d&quot;, ret); abus_cleanup (&abus); exit(EXIT_FAILURE); } printf(&quot;New value: %s=%d&quot;, attr_name, my_int); abus_cleanup (&abus); return EXIT_SUCCESS; } ,[object Object]
local unix sockets Fourth example : working with event libabus libabus libabus client service
example-svc-event.c #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <errno.h> #include &quot;abus.h&quot; static void chomp(char *s) { int len = strlen(s); if (len > 0 && s[len-1] == '') s[len-1] = ''; } int main(int argc, char **argv) { abus_t abus; char s[128]; abus_init (&abus); #define MYSVCNAME &quot;examplesvc&quot; #define MYEVTNAME &quot;enter_pressed&quot; abus_decl_event (&abus, MYSVCNAME, MYEVTNAME, &quot;Event sent each time the ENTER key is press. Serves as publish/subscribe example.&quot;, &quot;typed_char:s:keys pressed before the ENTER key&quot;); /* cheap event generator: press ENTER key on stdin Attached to the event, the chars typed in before the ENTER key */ while (fgets(s, sizeof(s), stdin) != NULL) { json_rpc_t json_rpc; chomp(s); abus_request_event_init (&abus, MYSVCNAME, MYEVTNAME, &json_rpc); json_rpc_append_str(&json_rpc, &quot;typed_char&quot;, s); abus_request_event_publish (&abus, &json_rpc, 0); abus_request_event_cleanup (&abus, &json_rpc); } abus_cleanup (&abus); return EXIT_SUCCESS; } ,[object Object]
http://abus.googlecode.com/svn/doc/HEAD/html/examples.html More example available here : ,[object Object]
Advance abus
abus-send [options] SERVICE.METHOD [key:[bfilsae]]=value]... -h, --help  this help message -t, --timeout=TIMEOUT  timeout in milliseconds (1000) -v, --verbose  verbose -V, --version  version of A-Bus -y, --async  asynchronous query -w, --wait-async  wait for asynchronous query, without callback Some examples: Global introspection: abus-send myAbusService. Calling a method without parameters: abus-send myAbusService.getDeviceState Calling a method with parameters: abus-send myAbusService.setDeviceState   newState:b=false Getting an object: abus-send myAbusService.get deviceinfo. abus-send myAbusService.get &quot;&quot; ,[object Object]
An abus-monitor should come in the future. ,[object Object]
If you want that the libabus dump the json messages to stdout, you just have to export a variable :  export ABUS_MSG_VERBOSE=1 That will generate such trace: ##  4067 <- 00083:70 {&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;DmngCoreStub.getConfig&quot;,&quot;id&quot;:1,&quot;params&quot;:{}} ##  4067 -> 00083:2220 {&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;result&quot;:{&quot;device.stateID&quot;:false,&quot;device.actionID&quot;:0,&quot;device.languageID&quot;:0,&quot;device.uptime&quot;:742,&quot;mainPower.isPowerConnected&quot;:0,&quot;mainPower.batteryLevel&quot;:41,&quot;audio.ModeID&quot;:1,&quot;audio.BitRate&quot;:64,&quot;video.ModeType&quot;:0,&quot;video.BitRate&quot;:44,&quot;video.Frequency&quot;:0,&quot;liveProfile&quot;:[{&quot;id&quot;:0,&quot;name&quot;:&quot;INTERVIEW&quot;,&quot;rate&quot;:12,&quot;modeID&quot;:0,&quot;studioID&quot;:0,&quot;resolutionID&quot;:0,&quot;videoInputID&quot;:0,&quot;delay&quot;:12},{&quot;id&quot;:1,&quot;name&quot;:&quot;BALANCED&quot;,&quot;rate&quot;:5,&quot;modeID&quot;:1,&quot;studioID&quot;:4,&quot;resolutionID&quot;:1,&quot;videoInputID&quot;:1,&quot;delay&quot;:14},{&quot;id&quot;:2,&quot;name&quot;:&quot;QUALITY&quot;,&quot;rate&quot;:6,&quot;modeID&quot;:1,&quot;studioID&quot;:3,&quot;resolutionID&quot;:0,&quot;videoInputID&quot;:2,&quot;delay&quot;:20},{&quot;id&quot;:3,&quot;name&quot;:&quot;LOW DELAY&quot;,&quot;rate&quot;:4,&quot;modeID&quot;:1,&quot;studioID&quot;:2,&quot;resolutionID&quot;:0,&quot;videoInputID&quot;:1,&quot;delay&quot;:5},{&quot;id&quot;:4,&quot;name&quot;:&quot;BGAN&quot;,&quot;rate&quot;:2,&quot;modeID&quot;:0,&quot;studioID&quot;:0,&quot;resolutionID&quot;:1,&quot;videoInputID&quot;:2,&quot;delay&quot;:10}],&quot;studioListing&quot;:[{&quot;studioId&quot;:0,&quot;name&quot;:&quot;studio1&quot;,&quot;ipAddress&quot;:&quot;&quot;,&quot;channel&quot;:2,&quot;controlLink&quot;:true},{&quot;studioId&quot;:1,&quot;name&quot;:&quot;studio2&quot;,&quot;ipAddress&quot;:&quot;&quot;,&quot;channel&quot;:4,&quot;controlLink&quot;:false},{&quot;studioId&quot;:2,&quot;name&quot;:&quot;studio3&quot;,&quot;ipAddress&quot;:&quot;&quot;,&quot;channel&quot;:1,&quot;controlLink&quot;:true},{&quot;studioId&quot;:3,&quot;name&quot;:&quot;studio4&quot;,&quot;ipAddress&quot;:&quot;&quot;,&quot;channel&quot;:3,&quot;controlLink&quot;:true}],&quot;massstorageListing&quot;:[{&quot;id&quot;:0,&quot;devname&quot;:&quot;/dev/sda1&quot;,&quot;label&quot;:&quot;toto&quot;,&quot;uuid&quot;:&quot;110E8400-E29B-11D4-A716-446655440000&quot;,&quot;mountPoint&quot;:&quot;/tmp/disk1&quot;,&quot;totalSize&quot;:5000000,&quot;freeSize&quot;:500000,&quot;filesystem&quot;:39,&quot;type&quot;:0,&quot;isWrite&quot;:true},{&quot;id&quot;:1,&quot;devname&quot;:&quot;/dev/sda2&quot;,&quot;label&quot;:&quot;&quot;,&quot;uuid&quot;:&quot;550e8400-e29b-41d4-a716-446655440000&quot;,&quot;mountPoint&quot;:&quot;/tmp/disk2&quot;,&quot;totalSize&quot;:2000000,&quot;freeSize&quot;:20000,&quot;filesystem&quot;:39,&quot;type&quot;:1,&quot;isWrite&quot;:false}],&quot;networkinterfaceListing&quot;:[{&quot;id&quot;:0,&quot;status&quot;:1,&quot;mode&quot;:0,&quot;type&quot;:0,&quot;tx&quot;:30,&quot;rx&quot;:6,&quot;bandwitch&quot;:3,&quot;ifname&quot;:&quot;eth0&quot;,&quot;ipAddress&quot;:&quot;192.168.0.5&quot;,&quot;netmask&quot;:&quot;255.255.255.0&quot;,&quot;gateway&quot;:&quot;192.168.0.1&quot;},{&quot;id&quot;:1,&quot;status&quot;:1,&quot;mode&quot;:1,&quot;type&quot;:0,&quot;tx&quot;:26,&quot;rx&quot;:1,&quot;bandwitch&quot;:10,&quot;ifname&quot;:&quot;eth1&quot;,&quot;ipAddress&quot;:&quot;192.168.2.4&quot;,&quot;netmask&quot;:&quot;255.255.255.0&quot;,&quot;gateway&quot;:&quot;192.168.0.1&quot;},{&quot;id&quot;:2,&quot;status&quot;:1,&quot;mode&quot;:1,&quot;type&quot;:0,&quot;tx&quot;:19,&quot;rx&quot;:30,&quot;bandwitch&quot;:27,&quot;ifname&quot;:&quot;eth2&quot;,&quot;ipAddress&quot;:&quot;10.11.133.4&quot;,&quot;netmask&quot;:&quot;255.255.0.0&quot;,&quot;gateway&quot;:&quot;10.11.133.1&quot;},{&quot;id&quot;:3,&quot;status&quot;:1,&quot;mode&quot;:1,&quot;type&quot;:1,&quot;tx&quot;:48,&quot;rx&quot;:14,&quot;bandwitch&quot;:14,&quot;ifname&quot;:&quot;ath0&quot;,&quot;ipAddress&quot;:&quot;192.168.0.8&quot;,&quot;netmask&quot;:&quot;255.255.255.0&quot;,&quot;gateway&quot;:&quot;192.168.0.1&quot;}]},&quot;id&quot;:1} ,[object Object]
Here are some points for the abus evolution in the nearest future : - event management for web purpose - some security For more detail :  http://code.google.com/p/abus/wiki/ABusNotes ,[object Object]

Mais conteúdo relacionado

Mais procurados

Introduction to Swift programming language.
Introduction to Swift programming language.Introduction to Swift programming language.
Introduction to Swift programming language.Icalia Labs
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming LanguageGiuseppe Arici
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming LanguageAnıl Sözeri
 
Advanced python
Advanced pythonAdvanced python
Advanced pythonEU Edge
 
Advanced Python, Part 2
Advanced Python, Part 2Advanced Python, Part 2
Advanced Python, Part 2Zaar Hai
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overviewhesher
 
Introduction into ES6 JavaScript.
Introduction into ES6 JavaScript.Introduction into ES6 JavaScript.
Introduction into ES6 JavaScript.boyney123
 
Pig Introduction to Pig
Pig Introduction to PigPig Introduction to Pig
Pig Introduction to PigChris Wilkes
 
JavaScript 1 for high school
JavaScript 1 for high schoolJavaScript 1 for high school
JavaScript 1 for high schooljekkilekki
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)ujihisa
 
Funkcija, objekt, python
Funkcija, objekt, pythonFunkcija, objekt, python
Funkcija, objekt, pythonRobert Lujo
 
VIM for (PHP) Programmers
VIM for (PHP) ProgrammersVIM for (PHP) Programmers
VIM for (PHP) ProgrammersZendCon
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, SwiftYandex
 

Mais procurados (20)

Swift 2
Swift 2Swift 2
Swift 2
 
Vim Hacks
Vim HacksVim Hacks
Vim Hacks
 
Introduction to Swift programming language.
Introduction to Swift programming language.Introduction to Swift programming language.
Introduction to Swift programming language.
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming Language
 
Bash production guide
Bash production guideBash production guide
Bash production guide
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming Language
 
Developing iOS apps with Swift
Developing iOS apps with SwiftDeveloping iOS apps with Swift
Developing iOS apps with Swift
 
Advanced python
Advanced pythonAdvanced python
Advanced python
 
Advanced Python, Part 2
Advanced Python, Part 2Advanced Python, Part 2
Advanced Python, Part 2
 
Don't do this
Don't do thisDon't do this
Don't do this
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overview
 
ES6 and BEYOND
ES6 and BEYONDES6 and BEYOND
ES6 and BEYOND
 
Introduction into ES6 JavaScript.
Introduction into ES6 JavaScript.Introduction into ES6 JavaScript.
Introduction into ES6 JavaScript.
 
Pig Introduction to Pig
Pig Introduction to PigPig Introduction to Pig
Pig Introduction to Pig
 
JavaScript 1 for high school
JavaScript 1 for high schoolJavaScript 1 for high school
JavaScript 1 for high school
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)
 
Funkcija, objekt, python
Funkcija, objekt, pythonFunkcija, objekt, python
Funkcija, objekt, python
 
VIM for (PHP) Programmers
VIM for (PHP) ProgrammersVIM for (PHP) Programmers
VIM for (PHP) Programmers
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, Swift
 

Destaque

Open Source Creativity
Open Source CreativityOpen Source Creativity
Open Source CreativitySara Cannon
 
Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)maditabalnco
 
The impact of innovation on travel and tourism industries (World Travel Marke...
The impact of innovation on travel and tourism industries (World Travel Marke...The impact of innovation on travel and tourism industries (World Travel Marke...
The impact of innovation on travel and tourism industries (World Travel Marke...Brian Solis
 
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika AldabaLightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldabaux singapore
 
The Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post FormatsThe Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post FormatsBarry Feldman
 

Destaque (6)

Open Source Creativity
Open Source CreativityOpen Source Creativity
Open Source Creativity
 
Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)
 
The impact of innovation on travel and tourism industries (World Travel Marke...
The impact of innovation on travel and tourism industries (World Travel Marke...The impact of innovation on travel and tourism industries (World Travel Marke...
The impact of innovation on travel and tourism industries (World Travel Marke...
 
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job? Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
 
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika AldabaLightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
Lightning Talk #9: How UX and Data Storytelling Can Shape Policy by Mika Aldaba
 
The Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post FormatsThe Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post Formats
 

Semelhante a Abus at a glance

Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехБоремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехСбертех | SberTech
 
Implementing of classical synchronization problem by using semaphores
Implementing of classical synchronization problem by using semaphoresImplementing of classical synchronization problem by using semaphores
Implementing of classical synchronization problem by using semaphoresGowtham Reddy
 
C++ Interview Question And Answer
C++ Interview Question And AnswerC++ Interview Question And Answer
C++ Interview Question And AnswerJagan Mohan Bishoyi
 
C++ questions And Answer
C++ questions And AnswerC++ questions And Answer
C++ questions And Answerlavparmar007
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioPVS-Studio
 
Hooking signals and dumping the callstack
Hooking signals and dumping the callstackHooking signals and dumping the callstack
Hooking signals and dumping the callstackThierry Gayet
 
Effecient javascript
Effecient javascriptEffecient javascript
Effecient javascriptmpnkhan
 
in c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdfin c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdfstopgolook
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0Yaser Zhian
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyNikhil Mungel
 
1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answers1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answersAkash Gawali
 
Compiler Design and Construction COSC 5353Project Instructions -
Compiler Design and Construction COSC 5353Project Instructions -Compiler Design and Construction COSC 5353Project Instructions -
Compiler Design and Construction COSC 5353Project Instructions -LynellBull52
 
Unit 4
Unit 4Unit 4
Unit 4siddr
 
C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial javaTpoint s
 
李建忠、侯捷设计模式讲义
李建忠、侯捷设计模式讲义李建忠、侯捷设计模式讲义
李建忠、侯捷设计模式讲义yiditushe
 
Writing a TSDB from scratch_ performance optimizations.pdf
Writing a TSDB from scratch_ performance optimizations.pdfWriting a TSDB from scratch_ performance optimizations.pdf
Writing a TSDB from scratch_ performance optimizations.pdfRomanKhavronenko
 

Semelhante a Abus at a glance (20)

Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехБоремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
 
Implementing of classical synchronization problem by using semaphores
Implementing of classical synchronization problem by using semaphoresImplementing of classical synchronization problem by using semaphores
Implementing of classical synchronization problem by using semaphores
 
C++ Interview Question And Answer
C++ Interview Question And AnswerC++ Interview Question And Answer
C++ Interview Question And Answer
 
C++ questions And Answer
C++ questions And AnswerC++ questions And Answer
C++ questions And Answer
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-Studio
 
Memory Manglement in Raku
Memory Manglement in RakuMemory Manglement in Raku
Memory Manglement in Raku
 
Hooking signals and dumping the callstack
Hooking signals and dumping the callstackHooking signals and dumping the callstack
Hooking signals and dumping the callstack
 
Namespaces
NamespacesNamespaces
Namespaces
 
Boost tour 1_44_0_all
Boost tour 1_44_0_allBoost tour 1_44_0_all
Boost tour 1_44_0_all
 
Effecient javascript
Effecient javascriptEffecient javascript
Effecient javascript
 
in c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdfin c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdf
 
Cocoa heads 09112017
Cocoa heads 09112017Cocoa heads 09112017
Cocoa heads 09112017
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in Ruby
 
1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answers1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answers
 
Compiler Design and Construction COSC 5353Project Instructions -
Compiler Design and Construction COSC 5353Project Instructions -Compiler Design and Construction COSC 5353Project Instructions -
Compiler Design and Construction COSC 5353Project Instructions -
 
Unit 4
Unit 4Unit 4
Unit 4
 
C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial
 
李建忠、侯捷设计模式讲义
李建忠、侯捷设计模式讲义李建忠、侯捷设计模式讲义
李建忠、侯捷设计模式讲义
 
Writing a TSDB from scratch_ performance optimizations.pdf
Writing a TSDB from scratch_ performance optimizations.pdfWriting a TSDB from scratch_ performance optimizations.pdf
Writing a TSDB from scratch_ performance optimizations.pdf
 

Último

Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 

Último (20)

Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 

Abus at a glance