Simplified doc-site generation
[AGL/documentation.git] / docs / 4_APIs_and_Services / 4.3_Application_Framework_Binder / 6_Annexes / 6_LEGACY_Migration_from_v1_to_v2.md
1 ---
2 edit_link: ''
3 title: LEGACY Migration from v1 to v2
4 origin_url: >-
5   https://git.automotivelinux.org/src/app-framework-binder/plain/docs/legacy/afb-migration-v1-to-v2.md?h=master
6 ---
7
8 <!-- WARNING: This file is generated by fetch_docs.js using /home/boron/Documents/AGL/docs-webtemplate/site/_data/tocs/apis_services/master/app-framework-binder-developer-guides-api-services-book.yml -->
9
10 [LEGACY] Migration from binding V1 to binding V2
11 =======================================
12
13 > LEGACY!!! IT IS NOT EXPECTED THAT YOU STILL NEED THIS GUIDE.
14 >
15 > THIS GUIDE WILL BE REMOVED IN A NEAR FUTURE
16
17
18 The ***binding*** interface evolved from version 1 to version 2
19 for the following reasons:
20
21 - integration of the security requirements within the bindings
22 - simplification of the API (after developer feedbacks)
23 - removal of obscure features, cleanup
24
25 The ***binder*** can run ***bindings*** v1 and/or v2 in any combination.  
26 Thus moving from v1 to v2 is not enforced, there is no real need.
27
28 More, it is possible to write a dual ***binding***:
29
30 - a ***binding*** that implements the version 1 and the version 2.
31
32 However, IT IS HIGHLY RECOMMENDED TO SWITCH TO ONLY VERSION 2:
33
34 - any new development SHOULD start using ***binding*** V2
35 - existing ***bindings*** SHOULD migrate to the version 2
36
37 This guide covers the migration of bindings from version 1 to version 2.
38
39 It also explains some of the rationale taken when migrating from version 1 to version 2.
40
41 In the future, if ***binding*** api evolves to fresh versions (3, 4, ...)
42 it might be necessarily to write bindings implementing more than
43 just one version.  
44 For example:
45
46 - a ***binding*** being v2 AND v3 will resolve the issue of running on older and newer version of AGL. 
47
48 This should always be possible even if more complicated.
49
50 Important things to known when migrating
51 ----------------------------------------
52
53 One of the most important change when migrating from v1 to v2 is
54 that many functions use an hidden *common* variable.  
55 This affects the functions of the following classes:
56
57 - functions of class **daemon**:
58   - functions starting with **afb_daemon_...**
59   - functions for logging: **ERROR**, **WARNING**, **NOTICE**, **INFO**, **DEBUG**
60 - functions of class **service**:
61   - functions starting with **afb_service_...**
62 - callback functions:
63   - the register function (that is removed)
64   - the service init function
65   - the onevent function
66
67 For these functions, the first parameter is now implicit.
68
69 Let takes an example.  
70 For ***binding*** v1 you had to write:
71
72 ```C
73         afb_daemon_broadcast_event(afbitf->daemon, reason, description);
74 ```
75
76 For ***binding*** v2, you simply write:
77
78 ```C
79         afb_daemon_broadcast_event(reason, description);
80 ```
81
82 This simplification is possible because the header files included for the bindings
83 now provide a common variable for storing the **daemon** and **service** data.
84
85 As a programmer, you shouldn't care much about that hidden variable.  
86 It simplifies the job, that's all and that is the reason of the change.
87
88 An other important difference is between the version 1 and the version 2 is
89 on how the ***binding***'s **API** is documented.  
90 The version 2 emphasis the **OpenAPI v3** description of the **API**.  
91 For this reason, to avoid duplication of descriptions, only one description is expected:
92
93 - The **OpenAPI** one.
94
95 Task list for the migration
96 ---------------------------
97
98 This task list is:
99
100 1. Enforce use of binding v2 by setting **AFB_BINDING_VERSION**
101 1. Rewrite the main structure and the list of exported verbs
102 1. Adapt the init and callback functions
103 1. Removes the first parameter of functions of classes **daemon** and **service**
104 1. Consider where to emit logs for requests
105 1. Take care of store/unstore changes
106 1. Consider use of synchronous (sub)call requests
107 1. Optionally, removes explicit struct
108
109 The remaining chapters explain these task with more details.
110
111 Enforce use of binding v2 by setting AFB_BINDING_VERSION
112 --------------------------------------------------------
113
114 By defining **AFB_BINDING_VERSION** to **2** you switch to version 2.  
115 This is done as below.
116
117 ```C
118 #define AFB_BINDING_VERSION 2
119 #include <afb/afb-binding.h>
120 ```
121
122 After that you will get many errors when compiling.
123
124 Rewrite the main structures and the list of exported verbs
125 ---------------------------------------------------------
126
127 The structures describing the ***binding** changed from version 1 to version 2.
128
129 The structure for describing verbs changed to include security
130 requirements.
131
132 In version 1 it was:
133
134 ```C
135 struct afb_verb_desc_v1
136 {
137        const char *name;                       /* name of the verb */
138        enum afb_session_flags_v1 session;      /* authorization and session requirements of the verb */
139        void (*callback)(struct afb_req req);   /* callback function implementing the verb */
140        const char *info;                       /* textual description of the verb */
141 };
142 ```
143
144 In version 2 it becomes:
145
146 ```C
147 struct afb_verb_v2
148 {
149         const char *verb;                       /* name of the verb */
150         void (*callback)(struct afb_req req);   /* callback function implementing the verb */
151         const struct afb_auth *auth;            /* required authorization */
152         uint32_t session;                       /* authorization and session requirements of the verb */
153 };
154
155 ```
156
157 The migration of instances of that structure requires the following actions:
158
159 - rename field **name** to **verb**
160 - remove field **info**
161 - adapt field **session** if needed
162 - set field **auth** to NULL
163
164 Example:
165
166 ```C
167  { .name= "new",   .session= AFB_SESSION_NONE, .callback= new,   .info= "Starts a new game" }
168 ```
169
170 Becomes
171
172 ```C
173  { .verb = "new",   .session = AFB_SESSION_NONE, .callback = new, .auth = NULL }
174 ```
175
176 The field **auth** can be set to a value describing the requested
177 authorization.
178
179 The main describing structure also changed.
180
181 In version 1 it was:
182
183 ```C
184 struct afb_binding_desc_v1
185 {
186        const char *info;                       /* textual information about the binding */
187        const char *prefix;                     /* required prefix name for the binding */
188        const struct afb_verb_desc_v1 *verbs;   /* array of descriptions of verbs terminated by a NULL name */
189 };
190 ```
191
192 In version 2 it becomes:
193
194 ```C
195 struct afb_binding_v2
196 {
197         const char *api;                        /* api name for the binding */
198         const char *specification;              /* textual specification of the binding */
199         const struct afb_verb_v2 *verbs;        /* array of descriptions of verbs terminated by a NULL name */
200         int (*preinit)();                       /* callback at load of the binding */
201         int (*init)();                          /* callback for starting the service */
202         void (*onevent)(const char *event, struct json_object *object); /* callback for handling events */
203         unsigned noconcurrency: 1;              /* avoids concurrent requests to verbs */
204 };
205 ```
206
207 The migration of instances of that structure requires the following actions:
208
209 - declare, explore, name the structure as ```const struct afb_binding_v2 afbBindingV2```
210 - rename the field **prefix** to **api**
211 - remove the field **info**
212 - setup the fields **preinit**, **init**, **onevent** according to the next section
213 - set the field **noconcurrency** to the right value:
214   - to 1 if you want to avoid concurrent calls to verbs.
215   - to 0 if you allow concurrent calls to verbs.
216
217 Example:
218
219 ```C
220 static const struct afb_binding plugin_desc = {
221         .type = AFB_BINDING_VERSION_1,
222         .v1 = {
223                 .info = "Minimal Hello World Sample",
224                 .prefix = "hello",
225                 .verbs = verbs
226         }
227 ```
228
229 Becomes:
230
231 ```C
232 const struct afb_binding_v2 afbBindingV2 = {
233         .api = "hello",
234         .specification = NULL,
235         .verbs = verbs,
236         .preinit = preinit,
237         .init = init
238 };
239 ```
240
241 The **binder** now relies only on the exported names
242 to deduce the type of the binding.  
243 This make the main structure more simple.
244
245 Adapt the init and callback functions
246 -------------------------------------
247
248 The ***bindings*** version 1 defined 3 exported functions:
249
250 - **afbBindingV1Register**
251 - **afbBindingV1ServiceInit**
252 - **afbBindingV1ServiceEvent**
253
254 These function should not be exported any more and there definition changed.
255
256 The function **afbBindingV1Register** is no more used to describe the binding.  
257 When a binding has to take actions when it is loaded, it must set the field
258 **preinit** of the structure **afbBindingV2**.  
259 This field, this preinit, might be used to check features at load.  
260 When it returns a negative number, the ***binder*** stops before initializing any ***binding***.
261
262 The function **afbBindingV1ServiceInit** is replaced by the field **init**
263 of the structure **afbBindingV2**.  
264 The init function should return 0 in case of success or a negative error code
265 in case of problem.  
266 It is called during initialization of services.
267
268 The function **afbBindingV1ServiceEvent**is replaced by the field **onevent**
269 of the structure **afbBindingV2**.
270
271 The two functions **afbBindingV1Register** and **afbBindingV1ServiceInit**,
272 were taking as parameter the ***binder*** interface and the service interface respectively.  
273 These interfaces are now managed hiddenly for the **binding** by the **binder**.  
274 So the variable that ***bindings*** version used to store the ***binder*** interface
275 and the service interface are no more needed and can be removed.
276
277 Example:
278
279 ```C
280 const struct afb_binding_interface *interface;
281 struct afb_service service;
282
283 static const struct afb_binding plugin_desc = {
284         .type = AFB_BINDING_VERSION_1,
285         .v1 = {
286                 .info = "Minimal Hello World Sample",
287                 .prefix = "hello",
288                 .verbs = verbs
289         }
290 }
291
292 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
293 {
294         interface = itf;
295         NOTICE(interface, "binding register");
296         return &plugin_desc;
297 }
298
299 int afbBindingV1ServiceInit(struct afb_service svc)
300 {
301         service = svc;
302         NOTICE(interface, "binding init");
303         return 0;
304 }
305
306 void afbBindingV1ServiceEvent(const char *event, struct json_object *object)
307 {
308         NOTICE(interface, "onevent %s", event);
309 }
310 ```
311
312 Becomes:
313
314 ```C
315 static int preinit()
316 {
317         AFB_NOTICE("binding preinit (was register)");
318         return 0;
319 }
320
321 static int init()
322 {
323         AFB_NOTICE("binding init");
324         return 0;
325 }
326
327 static void onevent(const char *event, struct json_object *object)
328 {
329         AFB_NOTICE("onevent %s", event);
330 }
331
332 const struct afb_binding_v2 afbBindingV2 = {
333         .api = "hello",
334         .specification = NULL,
335         .verbs = verbs,
336         .preinit = preinit,
337         .init = init,
338         .onevent = onevent
339 };
340 ```
341
342 The two functions **afbBindingV1Register** and **afbBindingV1ServiceInit**,
343 were taking as parameter the ***binder*** interface and the service interface respectively.  
344 These interfaces are now managed hiddenly for the **binding** by the **binder**.  
345 So the variable that ***bindings*** version used to store the ***binder*** interface
346 and the service interface are no more needed and can be removed.
347
348 On the above example the following lines were removed:
349
350 ```C
351 const struct afb_binding_interface *interface;
352 struct afb_service service;
353
354         interface = itf;
355
356         service = svc;
357 ```
358
359 Removes the first parameter of functions of classes **daemon** and **service**
360 ------------------------------------------------------------------------------
361
362 As explained before, many functions loose there first
363 arguments, this are the functions of the following classes:
364
365 - functions of class **daemon**:
366   - functions starting with **afb_daemon_...**
367   - functions for logging: **ERROR**, **WARNING**, **NOTICE**, **INFO**, **DEBUG**
368 - functions of class **service**:
369   - functions starting with **afb_service_...**
370 - callback functions:
371   - the register function (that is removed)
372   - the service init function
373   - the onevent function
374
375 For these functions, the first parameter is now implicit.
376
377 Example:
378
379 ```C
380         afb_daemon_broadcast_event(afbitf->daemon, reason, description);
381 ```
382
383 Becomes:
384
385 ```C
386         afb_daemon_broadcast_event(reason, description);
387 ```
388
389 Also, to avoid possible conflicts, we introduced prefixed logging functions:  
390 the macros 
391
392 - **ERROR**
393 - **WARNING**
394 - **NOTICE**
395 - **INFO**
396 - **DEBUG** 
397
398 have now a prefixed version: 
399
400 - **AFB\_ERROR**
401 - **AFB\_WARNING**
402 - **AFB\_NOTICE**
403 - **AFB\_INFO**
404 - **AFB\_DEBUG**
405
406 It is now recommended to use the prefixed version.
407
408 Example:
409
410 ```C
411         NOTICE(interface, "hello plugin comes to live");
412 ```
413
414 Become:
415
416 ```C
417         NOTICE("hello plugin comes to live");
418 ```
419
420 or, better:
421
422 ```C
423         AFB_NOTICE("hello plugin comes to live");
424 ```
425
426 To remove definition of the un-prefixed versions of logging macros:
427
428 - **ERROR**
429 - **WARNING**
430 - **NOTICE**
431 - **INFO**
432 - **DEBUG** 
433
434 and just define 
435
436 - **AFB_BINDING_PRAGMA_NO_VERBOSE_UNPREFIX**
437
438 before to include **afb/afb-binding.h**.
439
440 ```C
441 #define AFB_BINDING_PRAGMA_NO_VERBOSE_UNPREFIX
442 #define AFB_BINDING_VERSION 2
443 #include <afb/afb-binding.h>
444 ```
445
446 Consider where to emit logs for requests
447 ----------------------------------------
448
449 The ***bindings*** v2 now allows to emit log messages associated to ***requests***.  
450 This feature is valuable when debugging because it allows to return
451 side information associated to a ***request***.
452
453 The defined macros for logging to requests are: 
454
455 - **AFB_REQ_ERROR**
456 - **AFB_REQ_WARNING**
457 - **AFB_REQ_NOTICE**
458 - **AFB_REQ_INFO**
459 - **AFB_REQ_DEBUG**
460
461 We encourage the use of these new logging facilities everywhere it makes sense.
462
463 Example:
464
465 ```C
466         INFO(afbitf, "method 'new' called for boardid %d", board->id);
467 ```
468
469 Might become:
470
471 ```C
472         AFB_REQ_INFO(req, "method 'new' called for boardid %d", board->id);
473 ```
474
475 Take care of store/unstore change
476 ---------------------------------
477
478 For efficiency, the version 2 redefined how storing/un-storing of
479 requests works.  
480 Storing request is needed for asynchronous handling of requests.
481
482 For ***bindings*** version, the signature of the functions were:
483
484 ```C
485 struct afb_req *afb_req_store(struct afb_req req);
486 struct afb_req afb_req_unstore(struct afb_req *req);
487 ```
488
489 For version 2 it becomes
490
491 ```C
492 struct afb_stored_req *afb_req_store(struct afb_req req);
493 struct afb_req afb_req_unstore(struct afb_stored_req *sreq);
494 ```
495
496 Where the structure ```struct afb_stored_req``` is opaque.
497
498 It should require few code change.
499
500 Also check the following chapter that explain that asynchronous (sub)calls
501 can be replaced by synchronous one, avoiding the need to store/unstore
502 requests.
503
504 Consider use of synchronous (sub)call requests
505 ----------------------------------------------
506
507 ***Bindings*** can emit requests for themselves (calls) or for
508 their clients (subcalls).  
509 With ***bindings*** version 2 comes also synchronous requests for both cases.
510
511 So when migrating to bindings version 2, a developer can consider
512 to replace the asynchronous requests (with asynchronous call back)
513 by synchronous ones.
514
515 See functions ***afb_service_call_sync*** and ***afb_req_subcall_sync***.
516
517 Optionally, removes explicit struct
518 -----------------------------------
519
520 The new definitions now includes **typedefs** for common
521 structures, as shown on below sample:
522
523 ```C
524 typedef struct afb_daemon               afb_daemon;
525 typedef struct afb_event                afb_event;
526 typedef struct afb_arg                  afb_arg;
527 typedef struct afb_req                  afb_req;
528 typedef struct afb_service              afb_service;
529 ```
530
531 So you can remove the keyword **struct** if it bores you.
532
533 Example:
534
535 ```C
536 static void verb(struct afb_req req)
537 {
538         ...
539 }
540 ```
541
542 Might become:
543
544 ```C
545 static void verb(afb_req req)
546 {
547         ...
548 }
549 ```
550
551 Example of migration
552 --------------------
553
554 The first ***binding*** that migrated from v1 to v2 was the sample **HelloWorld**.  
555 Here is shown the differences between the version 1 and the version 2.
556
557 ```diff
558 diff --git a/bindings/samples/HelloWorld.c b/bindings/samples/HelloWorld.c
559 index c6fa779..505aee3 100644
560 --- a/bindings/samples/HelloWorld.c
561 +++ b/bindings/samples/HelloWorld.c
562 @@ -21,9 +21,9 @@
563
564  #include <json-c/json.h>
565
566 +#define AFB_BINDING_VERSION 2
567  #include <afb/afb-binding.h>
568
569 -const struct afb_binding_interface *interface;
570  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
571
572  struct event
573 @@ -79,7 +80,7 @@ static int event_add(const char *tag, const char *name)
574          strcpy(e->tag, tag);
575
576          /* make the event */
577 -    e->event = afb_daemon_make_event(interface->daemon, name);
578 +    e->event = afb_daemon_make_event(name);
579          if (!e->event.closure) { free(e); return -1; }
580
581          /* link */
582 @@ -140,7 +141,7 @@ static void pingBug (struct afb_req request)
583  static void pingEvent(struct afb_req request)
584  {
585          json_object *query = afb_req_json(request);
586 -    afb_daemon_broadcast_event(interface->daemon, "event", json_object_get(query));
587 +    afb_daemon_broadcast_event("event", json_object_get(query));
588          ping(request, json_object_get(query), "event");
589  }
590
591 @@ -288,38 +289,43 @@ static void exitnow (struct afb_req request)
592          exit(0);
593  }
594
595 +static int preinit()
596 +{
597 +    AFB_NOTICE("hello binding comes to live");
598 +    return 0;
599 +}
600 +
601 +static int init()
602 +{
603 +    AFB_NOTICE("hello binding starting");
604 +    return 0;
605 +}
606 +
607  // NOTE: this sample does not use session to keep test a basic as possible
608  //       in real application most APIs should be protected with AFB_SESSION_CHECK
609 -static const struct afb_verb_desc_v1 verbs[]= {
610 -  {"ping"     , AFB_SESSION_NONE, pingSample  , "Ping Application Framework"},
611 -  {"pingfail" , AFB_SESSION_NONE, pingFail    , "Fails"},
612 -  {"pingnull" , AFB_SESSION_NONE, pingNull    , "Return NULL"},
613 -  {"pingbug"  , AFB_SESSION_NONE, pingBug     , "Do a Memory Violation"},
614 -  {"pingJson" , AFB_SESSION_NONE, pingJson    , "Return a JSON object"},
615 -  {"pingevent", AFB_SESSION_NONE, pingEvent   , "Send an event"},
616 -  {"subcall",   AFB_SESSION_NONE, subcall     , "Call api/verb(args)"},
617 -  {"subcallsync",   AFB_SESSION_NONE, subcallsync     , "Call api/verb(args)"},
618 -  {"eventadd",  AFB_SESSION_NONE, eventadd    , "adds the event of 'name' for the 'tag'"},
619 -  {"eventdel",  AFB_SESSION_NONE, eventdel    , "deletes the event of 'tag'"},
620 -  {"eventsub",  AFB_SESSION_NONE, eventsub    , "subscribes to the event of 'tag'"},
621 -  {"eventunsub",AFB_SESSION_NONE, eventunsub  , "unsubscribes to the event of 'tag'"},
622 -  {"eventpush", AFB_SESSION_NONE, eventpush   , "pushs the event of 'tag' with the 'data'"},
623 -  {"exit",      AFB_SESSION_NONE, exitnow     , "exits from afb-daemon"},
624 -  {NULL}
625 +static const struct afb_verb_v2 verbs[]= {
626 +  { "ping"     ,    pingSample , NULL, AFB_SESSION_NONE },
627 +  { "pingfail" ,    pingFail   , NULL, AFB_SESSION_NONE },
628 +  { "pingnull" ,    pingNull   , NULL, AFB_SESSION_NONE },
629 +  { "pingbug"  ,    pingBug    , NULL, AFB_SESSION_NONE },
630 +  { "pingJson" ,    pingJson   , NULL, AFB_SESSION_NONE },
631 +  { "pingevent",    pingEvent  , NULL, AFB_SESSION_NONE },
632 +  { "subcall",      subcall    , NULL, AFB_SESSION_NONE },
633 +  { "subcallsync",  subcallsync, NULL, AFB_SESSION_NONE },
634 +  { "eventadd",     eventadd   , NULL, AFB_SESSION_NONE },
635 +  { "eventdel",     eventdel   , NULL, AFB_SESSION_NONE },
636 +  { "eventsub",     eventsub   , NULL, AFB_SESSION_NONE },
637 +  { "eventunsub",   eventunsub , NULL, AFB_SESSION_NONE },
638 +  { "eventpush",    eventpush  , NULL, AFB_SESSION_NONE },
639 +  { "exit",         exitnow    , NULL, AFB_SESSION_NONE },
640 +  { NULL}
641  };
642
643 -static const struct afb_binding plugin_desc = {
644 -    .type = AFB_BINDING_VERSION_1,
645 -    .v1 = {
646 -        .info = "Minimal Hello World Sample",
647 -        .prefix = "hello",
648 -        .verbs = verbs
649 -    }
650 +const struct afb_binding_v2 afbBindingV2 = {
651 +    .api = "hello",
652 +    .specification = NULL,
653 +    .verbs = verbs,
654 +    .preinit = preinit,
655 +    .init = init
656  };
657
658 -const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
659 -{
660 -    interface = itf;
661 -    NOTICE(interface, "hello plugin comes to live");
662 -    return &plugin_desc;
663 -}
664 ```