amfapp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /** @file amfapp.c
  2. *
  3. * Copyright (c) 2006 Ericsson AB.
  4. * Author: Hans Feldt, Anders Eriksson, Lars Holm
  5. * - Refactoring of code into several AMF files
  6. * - Constructors/destructors
  7. * - Serializers/deserializers
  8. *
  9. * All rights reserved.
  10. *
  11. *
  12. * This software licensed under BSD license, the text of which follows:
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice,
  18. * this list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  23. * contributors may be used to endorse or promote products derived from this
  24. * software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  36. * THE POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * AMF Application Class implementation
  39. *
  40. * This file contains functions for handling the AMF applications. It can
  41. * be viewed as the implementation of the AMF Application class
  42. * as described in SAI-Overview-B.02.01. The SA Forum specification
  43. * SAI-AIS-AMF-B.02.01 has been used as specification of the behaviour
  44. * and is referred to as 'the spec' below.
  45. *
  46. * The functions in this file are responsible for:
  47. * - on request start the service groups it contains
  48. * - on request order the service groups to assign workload to all
  49. * service units contained in the service group, level by level
  50. * - to handle administrative operation support for the application (FUTURE)
  51. *
  52. * The cluster class contains the following state machines:
  53. * - administrative state machine (ADSM)
  54. * - availability control state machine (ACSM)
  55. *
  56. * The administrative state machine will be implemented in the future.
  57. *
  58. * ACSM handles initial start of an application. In the future it will also
  59. * handle administrative commands on the application as described in paragraph
  60. * 7.4 of the spec. ACSM includes two stable states (UNINSTANTIATED and
  61. * STARTED) and a number of states to control the transition between the
  62. * stable states.
  63. *
  64. * The application is in state UNINSTANTIATED when the application starts.
  65. * (In the future this state will also be assumed after the LOCK_INSTANTIATION
  66. * administrative command.)
  67. *
  68. * State WORKLOAD_ASSIGNED is assumed when the application has been initially
  69. * started and will in the future be re-assumed after the administrative
  70. * command RESTART have been executed.
  71. *
  72. * 1. AMF Synchronization Control State Machine
  73. * =========================================
  74. *
  75. * 1.1 State Transition Table
  76. *
  77. * State: Event: Action: New state:
  78. * ===========================================================================
  79. * UNINSTANTIATED start A6,A1 STARTING_SGS
  80. * STARTING_SGS start [C4] A7
  81. * STARTING_SGS sg_started [C1] A8,A9 STARTED
  82. * STARTED start A6,A1 STARTING_SGS
  83. * STARTED assign_workload A3 ASSIGNING_WORKLOAD
  84. * ASSIGNING_WORKLOAD assign_workload A7
  85. * ASSIGNING_WORKLOAD start A7
  86. * ASSIGNING_WORKLOAD sg_assigned [C2] A10,A9 WORKLOAD_ASSIGNED
  87. * WORKLOAD_ASSIGNED start A6,A1 STARTING_SGS
  88. * WORKLOAD_ASSIGNED assign_workload A3 ASSIGNING_WORKLOAD
  89. *
  90. * 1.2 State Description
  91. * =====================
  92. * UNINSTANTIATED - No SUs within the SGs contained in the application have been
  93. * instantiated.
  94. * STARTING_SGS - Waiting for the contained SGs to start.
  95. * STARTED - No SUs within the SGs contained in the application are in the
  96. * process of beein instantiated. Either the SUs are instantiated or
  97. * instantiation was not possible or instantiation has failed.
  98. * ASSIGNING_WORKLOAD - Waiting for the contained SGs to indicate they have
  99. * assigned workload to its SUs.
  100. * WORKLOAD_ASSIGNED - at least some workload has been assigned to the SUs that
  101. * are in-service.
  102. *
  103. * 1.3 Actions
  104. * ===========
  105. * A1 - [foreach sg in application] sg_start
  106. * A2 -
  107. * A3 - [foreach sg in application] sg_assign
  108. * A4 -
  109. * A5 -
  110. * A6 - save value of received node parameter
  111. * A7 - defer the event
  112. * A8 - [node == NULL] cluster_application_started else node_application_started
  113. * A9 - recall defered events
  114. * A10 - [node == NULL] cluster_application_assigned else
  115. * node_application_assigned
  116. *
  117. * 1.4 Guards
  118. * ==========
  119. * C1 - No sg has availability control state == INSTANTIATING_SERVICE_UNITS
  120. * C2 - All sgs have availability control state == IDLE
  121. * C3 -
  122. * C4 - saved node value != received node value
  123. */
  124. #include <assert.h>
  125. #include "amf.h"
  126. #include "print.h"
  127. #include "util.h"
  128. /******************************************************************************
  129. * Internal (static) utility functions
  130. *****************************************************************************/
  131. int no_su_is_instantiating (struct amf_application *app)
  132. {
  133. struct amf_sg *sg;
  134. struct amf_su *su;
  135. int all_su_instantiated = 1;
  136. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  137. for (su = sg->su_head; su != NULL; su = su->next) {
  138. if (su->saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATING) {
  139. all_su_instantiated = 0;
  140. break;
  141. }
  142. }
  143. }
  144. return all_su_instantiated;
  145. }
  146. #ifdef COMPILE_OUT
  147. static int all_sg_started (struct amf_application *app)
  148. {
  149. struct amf_sg *sg;
  150. int all_su_instantiated = 1;
  151. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  152. if (sg->avail_state == SG_AC_InstantiatingServiceUnits) {
  153. all_su_instantiated = 0;
  154. break;
  155. }
  156. }
  157. return all_su_instantiated;
  158. }
  159. #endif
  160. static int all_sg_assigned (struct amf_application *app)
  161. {
  162. struct amf_sg *sg;
  163. int all_sg_assigned = 1;
  164. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  165. if (sg->avail_state != SG_AC_Idle) {
  166. all_sg_assigned = 0;
  167. break;
  168. }
  169. }
  170. return all_sg_assigned;
  171. }
  172. /******************************************************************************
  173. * Event methods
  174. *****************************************************************************/
  175. void amf_application_start (
  176. struct amf_application *app, struct amf_node *node)
  177. {
  178. struct amf_sg *sg;
  179. ENTER ("'%s'", app->name.value);
  180. assert (app != NULL);
  181. switch (app->acsm_state) {
  182. case APP_AC_UNINSTANTIATED:
  183. app->node_to_start = node;
  184. app->acsm_state = APP_AC_STARTING_SGS;
  185. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  186. amf_sg_start (sg, node);
  187. }
  188. break;
  189. case APP_AC_STARTING_SGS:
  190. if (app->node_to_start == node) {
  191. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  192. amf_sg_start (sg, node);
  193. }
  194. } else {
  195. /* TODO: Save the start request until state == APP_AC_STARTED */
  196. log_printf (LOG_LEVEL_ERROR, "Request to start application"
  197. " =%s in state = %d",app->name.value, app->acsm_state);
  198. openais_exit_error (AIS_DONE_FATAL_ERR);
  199. }
  200. break;
  201. case APP_AC_STARTED:
  202. /* TODO: Recall defered events */
  203. app->node_to_start = node;
  204. app->acsm_state = APP_AC_STARTING_SGS;
  205. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  206. amf_sg_start (sg, node);
  207. }
  208. break;
  209. case APP_AC_ASSIGNING_WORKLOAD:
  210. /* TODO: Save the start request until state == APP_AC_STARTED */
  211. log_printf (LOG_LEVEL_ERROR, "Request to start application"
  212. " =%s in state = %d (should be defered)",
  213. app->name.value, app->acsm_state);
  214. openais_exit_error (AIS_DONE_FATAL_ERR);
  215. break;
  216. case APP_AC_WORKLOAD_ASSIGNED:
  217. app->node_to_start = node;
  218. app->acsm_state = APP_AC_STARTING_SGS;
  219. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  220. amf_sg_start (sg, node);
  221. }
  222. break;
  223. default:
  224. assert (0);
  225. break;
  226. }
  227. }
  228. void amf_application_assign_workload (
  229. struct amf_application *app, struct amf_node *node)
  230. {
  231. struct amf_sg *sg;
  232. /*
  233. * TODO: dependency level ignored
  234. * Each dependency level should be looped and amf_sg_assign_si
  235. * called several times.
  236. */
  237. assert (app != NULL);
  238. app->node_to_start = node;
  239. switch (app->acsm_state) {
  240. case APP_AC_WORKLOAD_ASSIGNED:
  241. TRACE1 ("APP_AC_WORKLOAD_ASSIGNED");
  242. /* Fall through */
  243. case APP_AC_STARTED: {
  244. int posible_to_assign_si = 0;
  245. app->acsm_state = APP_AC_ASSIGNING_WORKLOAD;
  246. for (sg = app->sg_head; sg != NULL; sg = sg->next) {
  247. if (amf_sg_assign_si_req (sg, 0)) {
  248. posible_to_assign_si = 1;
  249. }
  250. }
  251. if (posible_to_assign_si == 0) {
  252. app->acsm_state = APP_AC_WORKLOAD_ASSIGNED;
  253. }
  254. break;
  255. }
  256. case APP_AC_ASSIGNING_WORKLOAD:
  257. if (app->node_to_start == node) {
  258. /*Calling object has violated the contract !*/
  259. assert (0);
  260. } else {
  261. /*
  262. * TODO: Save the request to assign workload until state ==
  263. * WORKLOAD_ASSIGNED
  264. */
  265. log_printf (LOG_LEVEL_ERROR, "Request to assign workload to"
  266. " application =%s in state = %d (should be defered)",
  267. app->name.value, app->acsm_state);
  268. openais_exit_error (AIS_DONE_FATAL_ERR);
  269. }
  270. break;
  271. default:
  272. /*Calling object has violated the contract !*/
  273. assert (0);
  274. break;
  275. }
  276. }
  277. /******************************************************************************
  278. * Event response methods
  279. *****************************************************************************/
  280. void amf_application_sg_started (
  281. struct amf_application *app, struct amf_sg *sg, struct amf_node *node)
  282. {
  283. ENTER ("'%s'", app->name.value);
  284. assert (app != NULL);
  285. switch (app->acsm_state) {
  286. case APP_AC_STARTING_SGS:
  287. if (no_su_is_instantiating (app)) {
  288. app->acsm_state = APP_AC_STARTED;
  289. if (app->node_to_start == NULL) {
  290. amf_cluster_application_started (app->cluster, app);
  291. } else {
  292. amf_node_application_started (app->node_to_start, app);
  293. }
  294. }
  295. break;
  296. default:
  297. log_printf (LOG_LEVEL_ERROR, "amf_application_sg_started()"
  298. " called in state = %d", app->acsm_state);
  299. openais_exit_error (AIS_DONE_FATAL_ERR);
  300. break;
  301. }
  302. }
  303. void amf_application_sg_assigned (
  304. struct amf_application *app, struct amf_sg *sg)
  305. {
  306. ENTER ("'%s'", app->name.value);
  307. assert (app != NULL);
  308. switch (app->acsm_state) {
  309. case APP_AC_ASSIGNING_WORKLOAD:
  310. if (all_sg_assigned (app)){
  311. app->acsm_state = APP_AC_WORKLOAD_ASSIGNED;
  312. if (app->node_to_start == NULL){
  313. amf_cluster_application_workload_assigned (app->cluster, app);
  314. } else {
  315. amf_node_application_workload_assigned (app->node_to_start, app);
  316. }
  317. }
  318. break;
  319. default:
  320. log_printf (LOG_LEVEL_ERROR, "amf_application_sg_assigned()"
  321. " called in state = %d", app->acsm_state);
  322. openais_exit_error (AIS_DONE_FATAL_ERR);
  323. break;
  324. }
  325. }
  326. /******************************************************************************
  327. * General methods
  328. *****************************************************************************/
  329. void amf_application_init (void)
  330. {
  331. log_init ("AMF");
  332. }
  333. struct amf_application *amf_application_new (struct amf_cluster *cluster) {
  334. struct amf_application *app = amf_calloc (1, sizeof (struct amf_application));
  335. app->cluster = cluster;
  336. app->next = cluster->application_head;
  337. cluster->application_head = app;
  338. app->acsm_state = APP_AC_UNINSTANTIATED;
  339. return app;
  340. }
  341. void amf_application_delete (struct amf_application *app)
  342. {
  343. struct amf_sg *sg;
  344. struct amf_si *si;
  345. assert (app != NULL);
  346. for (sg = app->sg_head; sg != NULL;) {
  347. struct amf_sg *tmp = sg;
  348. sg = sg->next;
  349. amf_sg_delete (tmp);
  350. }
  351. for (si = app->si_head; si != NULL;) {
  352. struct amf_si *tmp = si;
  353. si = si->next;
  354. amf_si_delete (tmp);
  355. }
  356. free (app);
  357. }
  358. void *amf_application_serialize (
  359. struct amf_application *app, int *len)
  360. {
  361. char *buf = NULL;
  362. int offset = 0, size = 0;
  363. assert (app != NULL);
  364. TRACE8 ("%s", app->name.value);
  365. buf = amf_serialize_SaNameT (buf, &size, &offset, &app->name);
  366. buf = amf_serialize_SaUint32T (
  367. buf, &size, &offset, app->saAmfApplicationAdminState);
  368. buf = amf_serialize_SaUint32T (
  369. buf, &size, &offset, app->saAmfApplicationCurrNumSG);
  370. buf = amf_serialize_SaStringT (
  371. buf, &size, &offset, app->clccli_path);
  372. buf = amf_serialize_SaUint32T (
  373. buf, &size, &offset, app->acsm_state);
  374. *len = offset;
  375. return buf;
  376. }
  377. struct amf_application *amf_application_deserialize (
  378. struct amf_cluster *cluster, char *buf) {
  379. char *tmp = buf;
  380. struct amf_application *app = amf_application_new (cluster);
  381. tmp = amf_deserialize_SaNameT (tmp, &app->name);
  382. tmp = amf_deserialize_SaUint32T (tmp, &app->saAmfApplicationAdminState);
  383. tmp = amf_deserialize_SaUint32T (tmp, &app->saAmfApplicationCurrNumSG);
  384. tmp = amf_deserialize_SaStringT (tmp, &app->clccli_path);
  385. tmp = amf_deserialize_SaUint32T (tmp, &app->acsm_state);
  386. return app;
  387. }
  388. struct amf_application *amf_application_find (
  389. struct amf_cluster *cluster, char *name)
  390. {
  391. struct amf_application *app;
  392. assert (cluster != NULL);
  393. for (app = cluster->application_head; app != NULL; app = app->next) {
  394. if (app->name.length == strlen(name) &&
  395. strncmp (name, (char*)app->name.value, app->name.length) == 0) {
  396. break;
  397. }
  398. }
  399. if (app == NULL) {
  400. dprintf ("App %s not found!", name);
  401. }
  402. return app;
  403. }