On Tue, Nov 15, 2011 at 11:53 AM, Enlightenment SVN
<no-re...@enlightenment.org> wrote:
> Log:
> Eina_xml based dbus introspection support. Thanks to Gustavo for the parser.
...
> +static void cb_introspect(void *data, DBusMessage *msg, DBusError *error)
> +{
> +   DBusError e;
> +   DBus *dbus = ((struct dbus_cache *)(data))->dbus;
> +   const char *xml_str;
> +
> +   if ((error) && (dbus_error_is_set(error)))
> +     {
> +        fprintf(stderr, "Error: DBus replied with error %s: %s\n",
> +                error->name, error->message);

convert it to eina log, create one domain for elv8 and other for
submodules such as elv8-dbus


> +
> +   struct DBus_Introspection_Parse_Ctxt *ctxt;
> +   ctxt = (struct DBus_Introspection_Parse_Ctxt *)calloc(1, sizeof(struct 
> DBus_Introspection_Parse_Ctxt));
> +   if (!eina_simple_xml_parse(xml_str, strlen(xml_str), EINA_TRUE, cb_parse, 
> ctxt))
> +     {
> +        fprintf(stderr, "Error: could not parse XML:\n%s\n", xml_str);

leak of ctxt!


> +        return;
> +     }
> +
> +   std::pair<std::map<const char *,DBus_Introspection_Parse_Ctxt 
> *>::iterator,bool> ret;

I'd not allocate ctxt, and would not make it into cache.

As I've explained at IRC, the correct structure for this is:

    path => {interfaces, children}
    children => [path1, path2, ...]

    interfaces = [interface1, interface2, ...]
    interface = {methods, signals, properties}

    methods = [method1, method2, method3...]
    method = {name, [argument1, argument2, ...]}
    signals = [signal1, signal2, signal3...]
    signal = {name, [argument1, argument2, ...]}
    properties = [property1, property2, property3...]
    property = {name, type}

Usage is one of:
   1 - explicit:
         var obj = bus.get_object(name, path);
         var iface = obj.get_interface(iface_name);
         iface.Method(p1, p2, p3);
   2 - implicit:
         var obj = bus.get_object(name, path);
         obj.Method(p1, p2, p3);

The first case is simple:
      iface = find_interface(iface_name) # mapping string => interface structure
      method = find_method(iface, signature) # mapping string =>
method structure

signature you need to compute for instance:
      ai  Method(o,s,i)
      ai  Method(o,s,name=value)  # named values will be supported in
elev8? parameters in a hash/map? Must define a policy, like sort
alphabetically and put at the end. Likely will have to have multiple
signatures per method!

The second case is bit more complex:
      ifaces = get_all_interfaces(obj) # mapping path => list of iface
structures
      methods = []
      for i in ifaces:
         m = find_method(i, signature) # mapping string => method structure
         if not m:
            continue
         methods.append(m)
      if len(methods) > 1:
          raise "Error: conflicting interfaces for " + signature + ":
"  + ", ".join(ifaces)
      else if len(methods) == 0:
          raise "Error: unknown method"
      method = methods[0]

Cache: method lookup is likely expensive, then cache it as LRU per
object, with a limit of dozens so you don't leak memory. Test case
must not go the slow path after the first iteration:

    for (i = 0; i < 1000; i++)
       obj.Method(i);

Assuming that services are implemented correctly the interfaces are
unique globally, then you can have:

    global map interfaces: "interface name" string => interface
    interface map methods: "method signature" string  => method
    object list interfaces: pair ("interface name" string, "interface
instance" interface)
    object lru methods: pair ("method signature" string, "method
instance" method)


===================================================================
> --- trunk/PROTO/elev8/src/bin/dbus_library.h    2011-11-15 13:34:28 UTC (rev 
> 65263)
> +++ trunk/PROTO/elev8/src/bin/dbus_library.h    2011-11-15 13:53:27 UTC (rev 
> 65264)
> @@ -4,21 +4,100 @@
>  #include <v8.h>
>  #include <dbus/dbus.h>
>  #include <E_DBus.h>
> -#include "dbus_introspect.h"
> +#include <Eina.h>
> +
>  #include <exception>
> -#include <sstream>
> +#include <map>
>  #include <iostream>
>  #include <fstream>
>
> +/* memory efficient structures to hold introspection information.
> + * maybe Eina_Inlist could be replaced with single array of structures
> + * (not to be confused with Eina_Array!!!!)
> + */
> +
> +struct DBus_Method_Argument
> +{
> +   EINA_INLIST;
> +   const char *type;
> +   const char *name;
> +   Eina_Bool is_output:1;
> +};

if you're using structs with malloc/free (C-like) then declare as
extern "C" {}, will avoid name marshling by C++ compiler, etc.

-- 
Gustavo Sverzut Barbieri
http://profusion.mobi embedded systems
--------------------------------------
MSN: barbi...@gmail.com
Skype: gsbarbieri
Mobile: +55 (19) 9225-2202

------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to