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