WRT binary marshal, we need a high performance, efficient, RPC (remote procedure call) mechanism. Options are: 1. Current RMD 2. Google protobufs: https://code.google.com/p/protobuf/ 3. A new RPC mechanism defined by Yang files. The user would define separate Yang files for RPC calls -- that is different than the configuration file. However, the RPC Yang file might include the configuration one if a RPC call requires a parameter that is also a config object.

Pros/Cons:

1. Current RMD Pros: exists

Cons: XML definition language is not convenient for editing. XML definition language is OpenClovis-specific Code is complex for a simple thing, hard to debug. Could be higher performance C-only

2. Protobufs: Pros: exists in common use -- defacto standard

Cons: in common use -- OpenClovis adds no value possibly least efficient of the 3 (uses pedantic >> and << for serialization) Not integrated with TIPC or IOC

3. Yang Pros: Uses standard file format Integrates well with SAFplus7 because we already use Yang for configuration We have experience with Yang file format We could make an extremely efficient data format.

Cons: we must create it

Given these options, I think we should do some basic investigation into #2 and #3.

For #2, we need to see how efficient it is, and how hard to add IOC/TIPC underneath.

For #3, that means creating a binary marshal format and a special y2cpp that generates RPC optimized code and data. For example, the classes would not be "Managed" -- that is:

   1 container Bar
   2 {
   3 leaf foo
   4   {
   5   type int;
   6   }
   7 }

->

   1 class Bar
   2 {
   3 public:
   4 int foo;
   5 };

Also I would like the code generator to be capable of generating an in-place implementation. That is:

   1 typedef GroupType  // Some complex data
   2   {
   3   leaf something
   4     {
   5     type int;
   6     }
   7   leaf somethingElse
   8     {
   9     type int;
  10     }
  11   }
  12 
  13 rpc getData
  14   {
  15  input 
  16    {
  17    leaf group 
  18      {
  19      type GroupType;
  20      }
  21    }
  22 
  23  output
  24    {
  25    leaf-list ret
  26      {
  27      type int;
  28      }
  29    }
  30   }

Classically could generate:

   1 class GroupType
   2 {
   3 int something;
   4 int somethingElse;
   5 }
   6 
   7 operator >> (Buffer& msg, GroupType& g) { ... }  // Generate binary marshal
   8 
   9 void getDataServer(Buffer* msg, Buffer* ret)
  10 {
  11   int rc;
  12   GroupType g;
  13   *msg >> g;  // Marshal and Demarshal functions are generated for each object
  14   rc = getData(&g);
  15   *ret << rc;
  16 }

In-place:

   1 void getDataServer(Buffer* msg, Buffer* ret, int swapNeeded)
   2 {
   3   GroupType *g = (GroupType*) (msg+GroupTypeOffset);
   4   if (swapNeeded)
   5     {
   6     // Do an "in-place" endian swap.  These are inlined functions for efficiency.
   7     swap(g->something);
   8     swap(g->somethingElse); 
   9     }
  10   *(ret+RetOffset) = getData(g);
  11 }

For complex structures, the in-place mechanism is extremely efficient because it:

  1. does no malloc/free
  2. does not call a large number of nested subfunctions that demarshal each individual thing -- function calls are actually expensive when you think about doing 50 of them just for a single RPC.
  3. does not copy, which both increases cache utilization and reduces expensive memory access.

SAFplus: Remote Procedure Call (last edited 2014-05-07 13:21:22 by AndrewStone)