amfsi.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. /** @file amfsi.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. * - Component/SU restart, SU failover
  7. * - Constructors/destructors
  8. * - Serializers/deserializers
  9. *
  10. * All rights reserved.
  11. *
  12. *
  13. * This software licensed under BSD license, the text of which follows:
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright notice,
  19. * this list of conditions and the following disclaimer.
  20. * - Redistributions in binary form must reproduce the above copyright notice,
  21. * this list of conditions and the following disclaimer in the documentation
  22. * and/or other materials provided with the distribution.
  23. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  24. * contributors may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  37. * THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * AMF Workload related classes Implementation
  40. *
  41. * This file contains functions for handling :
  42. * - AMF service instances(SI)
  43. * - AMF SI Dependency
  44. * - AMF SI Ranked SU
  45. * - AMF SI Assignment
  46. * - AMF component service instances (CSI)
  47. * - AMF CSI Assignment
  48. * - AMF CSI Type
  49. * - AMF CSI Attribute
  50. * The file can be viewed as the implementation of the classes listed above
  51. * as described in SAI-Overview-B.02.01. The SA Forum specification
  52. * SAI-AIS-AMF-B.02.01 has been used as specification of the behaviour
  53. * and is referred to as 'the spec' below.
  54. *
  55. * The functions in this file are responsible for:
  56. * - calculating and storing an SI_dependency_level integer per SI
  57. * - calculating and storing a csi_dependency_level integer per CSI
  58. * - on request change HA state of an SI or CSI in such a way that the
  59. * requirements regarding SI -> SI dependencies (paragraphs 3.9.1.1 and
  60. * 3.9.1.2) and CSI -> CSI dependencies (paragraph 3.9.1.3) are fully
  61. * respected
  62. *
  63. * The si_dependency_level is an attribute calculated at init (in the future
  64. * also at reconfiguration) which indicates dependencies between SIs as
  65. * an integer. The si_dependency level indicates to which extent an SI depends
  66. * on other SIs such that an SI that depends on no other SI is on
  67. * si_dependecy_level == 1, an SI that depends only on an SI on
  68. * si_dependency_level == 1 is on si_dependency-level == 2.
  69. * An SI that depends on several SIs gets a si_dependency_level that is one
  70. * unit higher than the SI with the highest si_dependency_level it depends on.
  71. *
  72. * The csi_dependency_level attribute works the same way.
  73. *
  74. * According to paragraph 3.9.1 of the spec, a change to or from the ACTIVE
  75. * HA state is not always allowed without first deactivate dependent SI and CSI
  76. * assignments. Dependencies between CSIs are absolute while an SI that depends
  77. * on another SI may tolerate that the SI on which it depends is inactive for a
  78. * configurable time (the tolerance time). The consequence of this is that a
  79. * request to change the SI state may require a sequence of requests to
  80. * components to assume a new HA state for a CSI-assignment and to guarantee
  81. * the dependency rules, the active response from the component has to be
  82. * awaited before next HA state can be set.
  83. *
  84. * This file implements an SI state machine that fully implements these rules.
  85. * This state machine is called SI Dependency Control State Machine (dcsm)
  86. * and has the following states:
  87. * - DEACTIVATED (there is no SI-assignment with active HA state)
  88. * - ACTIVATING (a request to set the ACTIVE HA state has been received and
  89. * setting ACTIVE HA states to the appropriate components are
  90. * in progress)
  91. * - ACTIVATED (there is at least one SI-assignment with the ACTIVE HA-state)
  92. * - DEACTIVATING (a request to de-activate an SI or only a specific CSI
  93. * within an SI has been received and setting the QUISCED
  94. * HA states to the appropriate components are in progress)
  95. * - DEPENDENCY_DEACTIVATING (the SI-SI dependency tolerance timer has expired
  96. * and setting the QUISCED HA states to the
  97. * appropriate components are in progress)
  98. * - DEPENDENCY_DEACTIVATED (as state DEACTIVATED but will automatically
  99. * transition to state ACTIVATING when the
  100. * dependency problem is solved, i.e. the SI on
  101. * which it depends has re-assumed the ACTIVE HA
  102. * state)
  103. * - SETTING (a request to change the HA state when neither the existing
  104. * nor the requested state is ACTIVE)
  105. *
  106. * This file also implements:
  107. * - SI: Assignment state (for report purposes)
  108. * - SI Assignment: HA state
  109. * - CSI Assignment: HA state
  110. *
  111. */
  112. #include <assert.h>
  113. #include <stdio.h>
  114. #include <stdlib.h>
  115. #include "amf.h"
  116. #include "print.h"
  117. #include "util.h"
  118. #include "aispoll.h"
  119. #include "main.h"
  120. /**
  121. * Check that all CSI assignments belonging to an SI assignment
  122. * has been removed.
  123. * @param si_assignment
  124. *
  125. * @return int
  126. */
  127. static int all_csi_assignments_removed (amf_si_assignment_t *si_assignment)
  128. {
  129. amf_csi_assignment_t *csi_assignment;
  130. amf_csi_t *csi;
  131. int all_removed = 1;
  132. for (csi = si_assignment->si->csi_head; csi != NULL; csi = csi->next) {
  133. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  134. csi_assignment = csi_assignment->next) {
  135. /*
  136. * If the CSI assignment and the SI assignment belongs to the
  137. * same SU, we have a match and can request the component to
  138. * remove the CSI.
  139. */
  140. if (name_match (&csi_assignment->comp->su->name,
  141. &si_assignment->su->name)) {
  142. if (csi_assignment->requested_ha_state !=
  143. csi_assignment->saAmfCSICompHAState) {
  144. all_removed = 0;
  145. }
  146. }
  147. }
  148. }
  149. return all_removed;
  150. }
  151. /**
  152. * Check if any CSI assignment belonging to SU has the requested
  153. * state.
  154. * @param su
  155. * @param hastate
  156. *
  157. * @return int
  158. */
  159. static int any_csi_has_hastate_in_su (struct amf_su *su, SaAmfHAStateT hastate)
  160. {
  161. struct amf_comp *component;
  162. struct amf_csi_assignment *csi_assignment;
  163. int exist = 0;
  164. for (component = su->comp_head; component != NULL;
  165. component = component->next) {
  166. csi_assignment = amf_comp_get_next_csi_assignment (component, NULL);
  167. while (csi_assignment != NULL) {
  168. if (csi_assignment->saAmfCSICompHAState == hastate) {
  169. exist = 1;
  170. goto done;
  171. }
  172. csi_assignment =
  173. amf_comp_get_next_csi_assignment (component, csi_assignment);
  174. }
  175. }
  176. done:
  177. return exist;
  178. }
  179. /**
  180. * Check if all CSI assignments belonging to a
  181. * an SI assignemnt has the requested state.
  182. * @param su
  183. * @param hastate
  184. *
  185. * @return int
  186. */
  187. static int all_csi_has_hastate_for_si (
  188. struct amf_si_assignment *si_assignment, SaAmfHAStateT hastate)
  189. {
  190. struct amf_comp *component;
  191. struct amf_csi_assignment *tmp_csi_assignment;
  192. int all = 1;
  193. for (component = si_assignment->su->comp_head; component != NULL;
  194. component = component->next) {
  195. tmp_csi_assignment = amf_comp_get_next_csi_assignment (component, NULL);
  196. while (tmp_csi_assignment != NULL) {
  197. if ((tmp_csi_assignment->si_assignment == si_assignment) &&
  198. (tmp_csi_assignment->saAmfCSICompHAState != hastate)) {
  199. all = 0;
  200. goto done;
  201. }
  202. tmp_csi_assignment =
  203. amf_comp_get_next_csi_assignment (component, tmp_csi_assignment);
  204. }
  205. }
  206. done:
  207. return all;
  208. }
  209. /**
  210. * Implements table 6 in 3.3.2.4
  211. * TODO: active & standby is not correct calculated acc. to
  212. * table. This knowledge is e.g. used in assign_si_assumed_cbfn
  213. * (sg.c)
  214. * @param csi_assignment
  215. */
  216. static void set_si_ha_state (struct amf_csi_assignment *csi_assignment)
  217. {
  218. SaAmfHAStateT old_ha_state =
  219. csi_assignment->si_assignment->saAmfSISUHAState;
  220. SaAmfAssignmentStateT old_assigment_state =
  221. amf_si_get_saAmfSIAssignmentState (csi_assignment->csi->si);
  222. if (all_csi_has_hastate_for_si (
  223. csi_assignment->si_assignment, SA_AMF_HA_ACTIVE)) {
  224. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_ACTIVE;
  225. }
  226. if (all_csi_has_hastate_for_si (
  227. csi_assignment->si_assignment, SA_AMF_HA_STANDBY)) {
  228. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_STANDBY;
  229. }
  230. if (any_csi_has_hastate_in_su (
  231. csi_assignment->comp->su, SA_AMF_HA_QUIESCING)) {
  232. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_QUIESCING;
  233. }
  234. if (any_csi_has_hastate_in_su (
  235. csi_assignment->comp->su, SA_AMF_HA_QUIESCED)) {
  236. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_QUIESCED;
  237. }
  238. /* log changes to HA state */
  239. if (old_ha_state != csi_assignment->si_assignment->saAmfSISUHAState) {
  240. log_printf (LOG_NOTICE, "SU HA state changed to '%s' for:\n"
  241. "\t\tSI '%s', SU '%s'",
  242. amf_ha_state (csi_assignment->si_assignment->saAmfSISUHAState),
  243. csi_assignment->si_assignment->si->name.value,
  244. csi_assignment->si_assignment->name.value);
  245. }
  246. /* log changes to assignment state */
  247. if (old_assigment_state !=
  248. amf_si_get_saAmfSIAssignmentState (csi_assignment->csi->si)) {
  249. log_printf (LOG_NOTICE, "SI Assignment state changed to '%s' for:\n"
  250. "\t\tSI '%s', SU '%s'",
  251. amf_assignment_state (
  252. amf_si_get_saAmfSIAssignmentState (csi_assignment->csi->si)),
  253. csi_assignment->si_assignment->si->name.value,
  254. csi_assignment->si_assignment->name.value);
  255. }
  256. }
  257. char *amf_csi_dn_make (struct amf_csi *csi, SaNameT *name)
  258. {
  259. int i = snprintf((char*) name->value, SA_MAX_NAME_LENGTH,
  260. "safCsi=%s,safSi=%s,safApp=%s",
  261. csi->name.value, csi->si->name.value,
  262. csi->si->application->name.value);
  263. assert (i <= SA_MAX_NAME_LENGTH);
  264. name->length = i;
  265. return(char *)name->value;
  266. }
  267. void amf_si_init (void)
  268. {
  269. log_init ("AMF");
  270. }
  271. void amf_si_comp_set_ha_state_done (
  272. struct amf_si *si, struct amf_csi_assignment *csi_assignment)
  273. {
  274. ENTER ("'%s', '%s'", si->name.value, csi_assignment->csi->name.value);
  275. set_si_ha_state (csi_assignment);
  276. assert (csi_assignment->si_assignment->assumed_callback_fn != NULL);
  277. /*
  278. * Report to caller when the requested SI assignment state is
  279. * confirmed.
  280. */
  281. if (csi_assignment->si_assignment->requested_ha_state ==
  282. csi_assignment->si_assignment->saAmfSISUHAState) {
  283. TRACE1("'%s', '%s'", si->name.value, csi_assignment->csi->name.value);
  284. csi_assignment->si_assignment->assumed_callback_fn (
  285. csi_assignment->si_assignment, 0);
  286. csi_assignment->si_assignment->assumed_callback_fn = NULL;
  287. }
  288. }
  289. void amf_si_activate (
  290. struct amf_si *si,
  291. void (*activated_callback_fn)(struct amf_si *si, int result))
  292. {
  293. struct amf_csi *csi;
  294. ENTER ("'%s'", si->name.value);
  295. for (csi = si->csi_head; csi != NULL; csi = csi->next) {
  296. struct amf_csi_assignment *csi_assignment;
  297. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  298. csi_assignment = csi_assignment->next) {
  299. csi_assignment->si_assignment->requested_ha_state =
  300. SA_AMF_HA_ACTIVE;
  301. /*
  302. * TODO: only active assignments should be set when dependency
  303. * levels are used.
  304. */
  305. csi_assignment->requested_ha_state = SA_AMF_HA_ACTIVE;
  306. amf_comp_hastate_set (csi_assignment->comp, csi_assignment);
  307. }
  308. }
  309. }
  310. void amf_si_comp_set_ha_state_failed (
  311. struct amf_si *si, struct amf_csi_assignment *csi_assignment)
  312. {
  313. ENTER ("");
  314. assert (0);
  315. }
  316. static void timer_function_ha_state_assumed (void *_si_assignment)
  317. {
  318. struct amf_si_assignment *si_assignment = _si_assignment;
  319. ENTER ("");
  320. si_assignment->saAmfSISUHAState = si_assignment->requested_ha_state;
  321. si_assignment->assumed_callback_fn (si_assignment, 0);
  322. }
  323. void amf_si_ha_state_assume (
  324. struct amf_si_assignment *si_assignment,
  325. void (*assumed_ha_state_callback_fn)(struct amf_si_assignment *si_assignment,
  326. int result))
  327. {
  328. struct amf_csi_assignment *csi_assignment;
  329. struct amf_csi *csi;
  330. int csi_assignment_cnt = 0;
  331. int hastate_set_done_cnt = 0;
  332. ENTER ("SI '%s' SU '%s' state %s", si_assignment->si->name.value,
  333. si_assignment->su->name.value,
  334. amf_ha_state (si_assignment->requested_ha_state));
  335. si_assignment->assumed_callback_fn = assumed_ha_state_callback_fn;
  336. for (csi = si_assignment->si->csi_head; csi != NULL; csi = csi->next) {
  337. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  338. csi_assignment = csi_assignment->next) {
  339. /*
  340. * If the CSI assignment and the SI assignment belongs to the
  341. * same SU, we have a match and can request the component to
  342. * change HA state.
  343. */
  344. if (name_match (&csi_assignment->comp->su->name,
  345. &si_assignment->su->name) &&
  346. (csi_assignment->saAmfCSICompHAState !=
  347. si_assignment->requested_ha_state)) {
  348. csi_assignment_cnt++;
  349. csi_assignment->requested_ha_state =
  350. si_assignment->requested_ha_state;
  351. amf_comp_hastate_set (csi_assignment->comp, csi_assignment);
  352. if (csi_assignment->saAmfCSICompHAState ==
  353. csi_assignment->requested_ha_state) {
  354. hastate_set_done_cnt++;
  355. }
  356. }
  357. }
  358. }
  359. /*
  360. * If the SU has only one component which is the faulty one, we
  361. * will not get an asynchronous response from the component.
  362. * This response (amf_si_comp_set_ha_state_done) is used to do
  363. * the next state transition. The asynchronous response is
  364. * simulated using a timeout instead.
  365. */
  366. if (csi_assignment_cnt == hastate_set_done_cnt) {
  367. poll_timer_handle handle;
  368. poll_timer_add (aisexec_poll_handle, 0, si_assignment,
  369. timer_function_ha_state_assumed, &handle);
  370. }
  371. }
  372. /**
  373. * Get number of active assignments for the specified SI
  374. * @param si
  375. *
  376. * @return int
  377. */
  378. int amf_si_get_saAmfSINumCurrActiveAssignments (struct amf_si *si)
  379. {
  380. int cnt = 0;
  381. struct amf_si_assignment *si_assignment;
  382. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  383. si_assignment = si_assignment->next) {
  384. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  385. cnt++;
  386. }
  387. }
  388. return cnt;
  389. }
  390. int amf_si_su_get_saAmfSINumCurrActiveAssignments (struct amf_si *si,
  391. struct amf_su *su)
  392. {
  393. int cnt = 0;
  394. struct amf_si_assignment *si_assignment;
  395. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  396. si_assignment = si_assignment->next) {
  397. if (si_assignment->su == su &&
  398. si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  399. cnt++;
  400. }
  401. }
  402. return cnt;
  403. }
  404. int amf_si_get_saAmfSINumCurrStandbyAssignments (struct amf_si *si)
  405. {
  406. int cnt = 0;
  407. struct amf_si_assignment *si_assignment;
  408. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  409. si_assignment = si_assignment->next) {
  410. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  411. cnt++;
  412. }
  413. }
  414. return cnt;
  415. }
  416. int amf_si_su_get_saAmfSINumCurrStandbyAssignments (struct amf_si *si,
  417. struct amf_su *su)
  418. {
  419. int cnt = 0;
  420. struct amf_si_assignment *si_assignment;
  421. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  422. si_assignment = si_assignment->next) {
  423. if (si_assignment->su == su &&
  424. si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  425. cnt++;
  426. }
  427. }
  428. return cnt;
  429. }
  430. SaAmfAssignmentStateT amf_si_get_saAmfSIAssignmentState (struct amf_si *si)
  431. {
  432. if ((amf_si_get_saAmfSINumCurrActiveAssignments (si) ==
  433. si->saAmfSIPrefActiveAssignments) &&
  434. (amf_si_get_saAmfSINumCurrStandbyAssignments (si) ==
  435. si->saAmfSIPrefStandbyAssignments)) {
  436. return SA_AMF_ASSIGNMENT_FULLY_ASSIGNED;
  437. } else if (amf_si_get_saAmfSINumCurrActiveAssignments (si) == 0) {
  438. return SA_AMF_ASSIGNMENT_UNASSIGNED;
  439. } else {
  440. return SA_AMF_ASSIGNMENT_PARTIALLY_ASSIGNED;
  441. }
  442. }
  443. void amf_csi_delete_assignments (struct amf_csi *csi, struct amf_su *su)
  444. {
  445. struct amf_csi_assignment *csi_assignment;
  446. ENTER ("'%s'", su->name.value);
  447. struct amf_csi_assignment **prev = &csi->assigned_csis;
  448. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  449. csi_assignment = csi_assignment->next) {
  450. if (csi_assignment->comp->su == su) {
  451. struct amf_csi_assignment *tmp = csi_assignment;
  452. *prev = csi_assignment->next;
  453. dprintf ("CSI assignment %s unlinked", tmp->name.value);
  454. free (tmp);
  455. } else {
  456. prev = &csi_assignment->next;
  457. }
  458. }
  459. }
  460. /**
  461. * Constructor for SI objects. Adds SI last in the ordered
  462. * list owned by the specified application. Always returns a
  463. * valid SI object, out-of-memory problems are handled here.
  464. * Default values are initialized.
  465. * @param app
  466. *
  467. * @return struct amf_si*
  468. */
  469. struct amf_si *amf_si_new (struct amf_application *app, char *name)
  470. {
  471. struct amf_si *tail = app->si_head;
  472. struct amf_si *si = amf_calloc (1, sizeof (struct amf_si));
  473. while (tail != NULL) {
  474. if (tail->next == NULL) {
  475. break;
  476. }
  477. tail = tail->next;
  478. }
  479. if (tail == NULL) {
  480. app->si_head = si;
  481. } else {
  482. tail->next = si;
  483. }
  484. si->application = app;
  485. /* setup default values from spec. */
  486. si->saAmfSIAdminState = SA_AMF_ADMIN_UNLOCKED;
  487. si->saAmfSIRank = 0;
  488. si->saAmfSIPrefActiveAssignments = 1;
  489. si->saAmfSIPrefStandbyAssignments = 1;
  490. si->assigned_sis = NULL;
  491. si->csi_head = NULL;
  492. setSaNameT (&si->name, name);
  493. return si;
  494. }
  495. void amf_si_delete (struct amf_si *si)
  496. {
  497. struct amf_si_assignment *si_assignment;
  498. struct amf_csi *csi;
  499. for (csi = si->csi_head; csi != NULL;) {
  500. struct amf_csi *tmp = csi;
  501. csi = csi->next;
  502. amf_csi_delete (tmp);
  503. }
  504. for (si_assignment = si->assigned_sis; si_assignment != NULL;) {
  505. struct amf_si_assignment *tmp = si_assignment;
  506. si_assignment = si_assignment->next;
  507. free (tmp);
  508. }
  509. free (si);
  510. }
  511. void *amf_si_serialize (struct amf_si *si, int *len)
  512. {
  513. char *buf = NULL;
  514. int offset = 0, size = 0;
  515. TRACE8 ("%s", si->name.value);
  516. buf = amf_serialize_SaNameT (buf, &size, &offset, &si->name);
  517. buf = amf_serialize_SaNameT (buf, &size, &offset,
  518. &si->saAmfSIProtectedbySG);
  519. buf = amf_serialize_SaUint32T (buf, &size, &offset, si->saAmfSIRank);
  520. buf = amf_serialize_SaUint32T (buf, &size, &offset, si->saAmfSINumCSIs);
  521. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  522. si->saAmfSIPrefActiveAssignments);
  523. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  524. si->saAmfSIPrefStandbyAssignments);
  525. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  526. si->saAmfSIAdminState);
  527. *len = offset;
  528. return buf;
  529. }
  530. struct amf_si *amf_si_deserialize (struct amf_application *app, char *buf)
  531. {
  532. char *tmp = buf;
  533. struct amf_si *si = amf_si_new (app, "");
  534. tmp = amf_deserialize_SaNameT (tmp, &si->name);
  535. tmp = amf_deserialize_SaNameT (tmp, &si->saAmfSIProtectedbySG);
  536. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIRank);
  537. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSINumCSIs);
  538. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIPrefActiveAssignments);
  539. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIPrefStandbyAssignments);
  540. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIAdminState);
  541. return si;
  542. }
  543. /*****************************************************************************
  544. * SI Assignment class implementation *
  545. ****************************************************************************/
  546. struct amf_si_assignment *amf_si_assignment_new (struct amf_si *si)
  547. {
  548. struct amf_si_assignment *si_assignment =
  549. amf_calloc (1, sizeof (struct amf_si_assignment));
  550. si_assignment->si = si;
  551. si_assignment->next = si->assigned_sis;
  552. si->assigned_sis = si_assignment;
  553. return si_assignment;
  554. }
  555. void *amf_si_assignment_serialize (
  556. amf_si_assignment_t *si_assignment, int *len)
  557. {
  558. char *buf = NULL;
  559. int offset = 0, size = 0;
  560. TRACE8 ("%s", si_assignment->name.value);
  561. buf = amf_serialize_SaNameT (buf, &size, &offset, &si_assignment->name);
  562. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  563. si_assignment->saAmfSISUHAState);
  564. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  565. si_assignment->requested_ha_state);
  566. *len = offset;
  567. return buf;
  568. }
  569. struct amf_si_assignment *amf_si_assignment_deserialize (
  570. struct amf_si *si, char *buf)
  571. {
  572. char *tmp = buf;
  573. struct amf_si_assignment *si_assignment = amf_si_assignment_new (si);
  574. tmp = amf_deserialize_SaNameT (tmp, &si_assignment->name);
  575. tmp = amf_deserialize_SaUint32T (tmp, &si_assignment->saAmfSISUHAState);
  576. tmp = amf_deserialize_SaUint32T (tmp, &si_assignment->requested_ha_state);
  577. si_assignment->su = amf_su_find (si->application->cluster,
  578. &si_assignment->name);
  579. return si_assignment;
  580. }
  581. struct amf_si *amf_si_find (struct amf_application *app, char *name)
  582. {
  583. struct amf_si *si;
  584. for (si = app->si_head; si != NULL; si = si->next) {
  585. if (si->name.length == strlen(name) &&
  586. strncmp (name, (char*)si->name.value, si->name.length) == 0) {
  587. break;
  588. }
  589. }
  590. if (si == NULL) {
  591. dprintf ("SI %s not found!", name);
  592. }
  593. return si;
  594. }
  595. /*****************************************************************************
  596. * CSI class implementation *
  597. ****************************************************************************/
  598. struct amf_csi *amf_csi_new (struct amf_si *si)
  599. {
  600. struct amf_csi *csi = amf_calloc (1, sizeof (struct amf_csi));
  601. csi->si = si;
  602. csi->next = si->csi_head;
  603. si->csi_head = csi;
  604. return csi;
  605. }
  606. void amf_csi_delete (struct amf_csi *csi)
  607. {
  608. struct amf_csi_assignment *csi_assignment;
  609. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;) {
  610. struct amf_csi_assignment *tmp = csi_assignment;
  611. csi_assignment = csi_assignment->next;
  612. free (tmp);
  613. }
  614. free (csi);
  615. }
  616. void *amf_csi_serialize (struct amf_csi *csi, int *len)
  617. {
  618. char *buf = NULL;
  619. int offset = 0, size = 0;
  620. TRACE8 ("%s", csi->name.value);
  621. buf = amf_serialize_SaNameT (buf, &size, &offset, &csi->name);
  622. buf = amf_serialize_SaNameT (buf, &size, &offset, &csi->saAmfCSTypeName);
  623. *len = offset;
  624. return buf;
  625. }
  626. struct amf_csi *amf_csi_deserialize (struct amf_si *si, char *buf)
  627. {
  628. char *tmp = buf;
  629. struct amf_csi *csi = amf_csi_new (si);
  630. tmp = amf_deserialize_SaNameT (tmp, &csi->name);
  631. tmp = amf_deserialize_SaNameT (tmp, &csi->saAmfCSTypeName);
  632. return csi;
  633. }
  634. struct amf_csi *amf_csi_find (struct amf_si *si, char *name)
  635. {
  636. struct amf_csi *csi;
  637. for (csi = si->csi_head; csi != NULL; csi = csi->next) {
  638. if (csi->name.length == strlen(name) &&
  639. strncmp (name, (char*)csi->name.value, csi->name.length) == 0) {
  640. break;
  641. }
  642. }
  643. if (csi == NULL) {
  644. dprintf ("CSI %s not found!", name);
  645. }
  646. return csi;
  647. }
  648. /*****************************************************************************
  649. * CSI Assignment class implementation *
  650. ****************************************************************************/
  651. struct amf_csi_assignment *amf_csi_assignment_new (struct amf_csi *csi)
  652. {
  653. struct amf_csi_assignment *csi_assignment =
  654. amf_calloc (1, sizeof (struct amf_csi_assignment));
  655. csi_assignment->csi = csi;
  656. csi_assignment->next = csi->assigned_csis;
  657. csi->assigned_csis = csi_assignment;
  658. return csi_assignment;
  659. }
  660. void *amf_csi_assignment_serialize (
  661. struct amf_csi_assignment *csi_assignment, int *len)
  662. {
  663. char *buf = NULL;
  664. int offset = 0, size = 0;
  665. TRACE8 ("%s", csi_assignment->name.value);
  666. buf = amf_serialize_SaNameT (buf, &size, &offset, &csi_assignment->name);
  667. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  668. csi_assignment->saAmfCSICompHAState);
  669. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  670. csi_assignment->requested_ha_state);
  671. *len = offset;
  672. return buf;
  673. }
  674. struct amf_si_assignment *si_assignment_find (
  675. struct amf_csi_assignment *csi_assignment)
  676. {
  677. struct amf_comp *component;
  678. struct amf_si_assignment *si_assignment = NULL;
  679. component = amf_comp_find(csi_assignment->csi->si->application->cluster,
  680. &csi_assignment->name);
  681. for (si_assignment = csi_assignment->csi->si->assigned_sis;
  682. si_assignment != NULL; si_assignment = si_assignment->next) {
  683. SaNameT su_name;
  684. amf_su_dn_make (component->su,&su_name);
  685. if (name_match(&su_name, &si_assignment->name)) {
  686. break;
  687. }
  688. }
  689. return si_assignment;
  690. }
  691. struct amf_csi_assignment *amf_csi_assignment_deserialize (
  692. struct amf_csi *csi, char *buf)
  693. {
  694. char *tmp = buf;
  695. struct amf_csi_assignment *csi_assignment = amf_csi_assignment_new (csi);
  696. tmp = amf_deserialize_SaNameT (tmp, &csi_assignment->name);
  697. tmp = amf_deserialize_SaUint32T (tmp,
  698. &csi_assignment->saAmfCSICompHAState);
  699. tmp = amf_deserialize_SaUint32T (tmp, &csi_assignment->requested_ha_state);
  700. csi_assignment->comp = amf_comp_find (csi->si->application->cluster,
  701. &csi_assignment->name);
  702. assert (csi_assignment->comp != NULL);
  703. csi_assignment->si_assignment = si_assignment_find(csi_assignment);
  704. return csi_assignment;
  705. }
  706. char *amf_csi_assignment_dn_make (
  707. struct amf_csi_assignment *csi_assignment, SaNameT *name)
  708. {
  709. SaNameT comp_name;
  710. struct amf_csi *csi = csi_assignment->csi;
  711. int i;
  712. amf_comp_dn_make (csi_assignment->comp, &comp_name);
  713. i = snprintf((char*) name->value, SA_MAX_NAME_LENGTH,
  714. "safCSIComp=%s,safCsi=%s,safSi=%s,safApp=%s",
  715. comp_name.value,
  716. csi->name.value, csi->si->name.value,
  717. csi->si->application->name.value);
  718. assert (i <= SA_MAX_NAME_LENGTH);
  719. name->length = i;
  720. return(char *)name->value;
  721. }
  722. struct amf_csi_assignment *amf_csi_assignment_find (
  723. struct amf_cluster *cluster, SaNameT *name)
  724. {
  725. struct amf_application *app;
  726. struct amf_si *si;
  727. struct amf_csi *csi;
  728. struct amf_csi_assignment *csi_assignment = NULL;
  729. char *app_name;
  730. char *si_name;
  731. char *csi_name;
  732. char *csi_assignment_name;
  733. char *buf;
  734. /* malloc new buffer since we need to write to the buffer */
  735. buf = amf_malloc (name->length + 1);
  736. memcpy (buf, name->value, name->length + 1);
  737. csi_assignment_name = strstr (buf, "safCSIComp=");
  738. csi_name = strstr (buf, "safCsi=");
  739. si_name = strstr (buf, "safSi=");
  740. app_name = strstr (buf, "safApp=");
  741. app_name++;
  742. app_name = strstr (app_name, "safApp=");
  743. if (csi_assignment_name == NULL || csi_name == NULL || si_name == NULL ||
  744. app_name == NULL) {
  745. goto end;
  746. }
  747. *(csi_name - 1) = '\0';
  748. *(si_name - 1) = '\0';
  749. *(app_name - 1) = '\0';
  750. /* jump to value */
  751. csi_assignment_name += 11;
  752. csi_name += 7;
  753. si_name += 6;
  754. app_name += 7;
  755. app = amf_application_find (cluster, app_name);
  756. if (app == NULL) {
  757. goto end;
  758. }
  759. si = amf_si_find (app, si_name);
  760. if (si == NULL) {
  761. goto end;
  762. }
  763. csi = amf_csi_find (si, csi_name);
  764. if (csi == NULL) {
  765. goto end;
  766. }
  767. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  768. csi_assignment = csi_assignment->next) {
  769. if (csi_assignment->name.length == strlen(csi_assignment_name) &&
  770. strncmp (csi_assignment_name,
  771. (char*)csi_assignment->name.value,
  772. csi_assignment->name.length) == 0) {
  773. goto end;
  774. }
  775. }
  776. end:
  777. assert(csi_assignment);
  778. free (buf);
  779. return csi_assignment;
  780. }
  781. struct amf_csi_attribute *amf_csi_attribute_new (struct amf_csi *csi)
  782. {
  783. struct amf_csi_attribute *csi_attribute =
  784. amf_calloc (1, sizeof (struct amf_csi_assignment));
  785. csi_attribute->next = csi->attributes_head;
  786. csi->attributes_head = csi_attribute;
  787. return csi_attribute;
  788. }
  789. void *amf_csi_attribute_serialize (
  790. struct amf_csi_attribute *csi_attribute, int *len)
  791. {
  792. char *buf = NULL;
  793. int i, offset = 0, size = 0;
  794. TRACE8 ("%s", csi_attribute->name);
  795. buf = amf_serialize_SaStringT (buf, &size, &offset, csi_attribute->name);
  796. /* count value and write to buf */
  797. for (i = 0; csi_attribute->value &&
  798. csi_attribute->value[i] != NULL; i++);
  799. buf = amf_serialize_SaUint32T (buf, &size, &offset, i);
  800. for (i = 0; csi_attribute->value &&
  801. csi_attribute->value[i] != NULL; i++) {
  802. buf = amf_serialize_SaStringT (
  803. buf, &size, &offset, csi_attribute->value[i]);
  804. }
  805. *len = offset;
  806. return buf;
  807. }
  808. struct amf_csi_attribute *amf_csi_attribute_deserialize (
  809. struct amf_csi *csi, char *buf)
  810. {
  811. char *tmp = buf;
  812. struct amf_csi_attribute *csi_attribute;
  813. int i;
  814. SaUint32T cnt;
  815. csi_attribute = amf_csi_attribute_new (csi);
  816. tmp = amf_deserialize_SaStringT (tmp, &csi_attribute->name);
  817. tmp = amf_deserialize_SaUint32T (tmp, &cnt);
  818. csi_attribute->value = amf_malloc ((cnt + 1) * sizeof (SaStringT*));
  819. for (i = 0; i < cnt; i++) {
  820. tmp = amf_deserialize_SaStringT (tmp, &csi_attribute->value[i]);
  821. }
  822. csi_attribute->value[i] = NULL;
  823. return csi_attribute;
  824. }
  825. void amf_si_assignment_remove (amf_si_assignment_t *si_assignment,
  826. async_func_t async_func)
  827. {
  828. struct amf_csi_assignment *csi_assignment;
  829. struct amf_csi *csi;
  830. int csi_assignment_cnt = 0;
  831. ENTER ("SI '%s' SU '%s' state %s", si_assignment->si->name.value,
  832. si_assignment->su->name.value,
  833. amf_ha_state (si_assignment->requested_ha_state));
  834. si_assignment->requested_ha_state = USR_AMF_HA_STATE_REMOVED;
  835. si_assignment->removed_callback_fn = async_func;
  836. for (csi = si_assignment->si->csi_head; csi != NULL; csi = csi->next) {
  837. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  838. csi_assignment = csi_assignment->next) {
  839. /*
  840. * If the CSI assignment and the SI assignment belongs to the
  841. * same SU, we have a match and can request the component to
  842. * remove the CSI.
  843. */
  844. if (name_match (&csi_assignment->comp->su->name,
  845. &si_assignment->su->name)) {
  846. csi_assignment_cnt++;
  847. csi_assignment->requested_ha_state = USR_AMF_HA_STATE_REMOVED;
  848. amf_comp_csi_remove (csi_assignment->comp, csi_assignment);
  849. }
  850. }
  851. }
  852. /*
  853. * If the SU has only one component which is the faulty one, we
  854. * will not get an asynchronous response from the component.
  855. * This response (amf_si_comp_set_ha_state_done) is used to do
  856. * the next state transition. The asynchronous response is
  857. * simulated using a timeout instead.
  858. */
  859. if (csi_assignment_cnt == 0) {
  860. amf_call_function_asynchronous (async_func, si_assignment);
  861. }
  862. }
  863. void amf_si_comp_csi_removed (
  864. struct amf_si *si, struct amf_csi_assignment *csi_assignment,
  865. SaAisErrorT error)
  866. {
  867. ENTER ("'%s', '%s'", si->name.value, csi_assignment->csi->name.value);
  868. assert (csi_assignment->si_assignment->removed_callback_fn != NULL);
  869. csi_assignment->saAmfCSICompHAState = USR_AMF_HA_STATE_REMOVED;
  870. /*
  871. * Report to caller when all requested CSI assignments has
  872. * been removed.
  873. */
  874. if (all_csi_assignments_removed(csi_assignment->si_assignment)) {
  875. csi_assignment->si_assignment->removed_callback_fn (
  876. csi_assignment->si_assignment);
  877. }
  878. }