amfsi.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  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 "logsys.h"
  117. #include "util.h"
  118. #include "aispoll.h"
  119. #include "main.h"
  120. LOGSYS_DECLARE_SUBSYS ("AMF", LOG_INFO);
  121. /**
  122. * Check that all CSI assignments belonging to an SI assignment
  123. * has been removed.
  124. * @param si_assignment
  125. *
  126. * @return int
  127. */
  128. static int all_csi_assignments_removed (amf_si_assignment_t *si_assignment)
  129. {
  130. amf_csi_assignment_t *csi_assignment;
  131. amf_csi_t *csi;
  132. int all_removed = 1;
  133. for (csi = si_assignment->si->csi_head; csi != NULL; csi = csi->next) {
  134. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  135. csi_assignment = csi_assignment->next) {
  136. /*
  137. * If the CSI assignment and the SI assignment belongs to the
  138. * same SU, we have a match and can request the component to
  139. * remove the CSI.
  140. */
  141. if (name_match (&csi_assignment->comp->su->name,
  142. &si_assignment->su->name)) {
  143. if (csi_assignment->requested_ha_state !=
  144. csi_assignment->saAmfCSICompHAState) {
  145. all_removed = 0;
  146. }
  147. }
  148. }
  149. }
  150. return all_removed;
  151. }
  152. /**
  153. * Check if any CSI assignment belonging to SU has the requested
  154. * state.
  155. * @param su
  156. * @param hastate
  157. *
  158. * @return int
  159. */
  160. static int any_csi_has_hastate_in_su (struct amf_su *su, SaAmfHAStateT hastate)
  161. {
  162. struct amf_comp *component;
  163. struct amf_csi_assignment *csi_assignment;
  164. int exist = 0;
  165. for (component = su->comp_head; component != NULL;
  166. component = component->next) {
  167. csi_assignment = amf_comp_get_next_csi_assignment (component, NULL);
  168. while (csi_assignment != NULL) {
  169. if (csi_assignment->saAmfCSICompHAState == hastate) {
  170. exist = 1;
  171. goto done;
  172. }
  173. csi_assignment =
  174. amf_comp_get_next_csi_assignment (component, csi_assignment);
  175. }
  176. }
  177. done:
  178. return exist;
  179. }
  180. /**
  181. * Check if all CSI assignments belonging to a
  182. * an SI assignemnt has the requested state.
  183. * @param su
  184. * @param hastate
  185. *
  186. * @return int
  187. */
  188. static int all_csi_has_hastate_for_si (
  189. struct amf_si_assignment *si_assignment, SaAmfHAStateT hastate)
  190. {
  191. struct amf_comp *component;
  192. struct amf_csi_assignment *tmp_csi_assignment;
  193. int all = 1;
  194. for (component = si_assignment->su->comp_head; component != NULL;
  195. component = component->next) {
  196. tmp_csi_assignment = amf_comp_get_next_csi_assignment (component, NULL);
  197. while (tmp_csi_assignment != NULL) {
  198. if ((tmp_csi_assignment->si_assignment == si_assignment) &&
  199. (tmp_csi_assignment->saAmfCSICompHAState != hastate)) {
  200. all = 0;
  201. goto done;
  202. }
  203. tmp_csi_assignment =
  204. amf_comp_get_next_csi_assignment (component, tmp_csi_assignment);
  205. }
  206. }
  207. done:
  208. return all;
  209. }
  210. /**
  211. * Implements table 6 in 3.3.2.4
  212. * TODO: active & standby is not correct calculated acc. to
  213. * table. This knowledge is e.g. used in assign_si_assumed_cbfn
  214. * (sg.c)
  215. * @param csi_assignment
  216. */
  217. static void set_si_ha_state (struct amf_csi_assignment *csi_assignment)
  218. {
  219. SaAmfHAStateT old_ha_state =
  220. csi_assignment->si_assignment->saAmfSISUHAState;
  221. SaAmfAssignmentStateT old_assigment_state =
  222. amf_si_get_saAmfSIAssignmentState (csi_assignment->csi->si);
  223. if (all_csi_has_hastate_for_si (
  224. csi_assignment->si_assignment, SA_AMF_HA_ACTIVE)) {
  225. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_ACTIVE;
  226. }
  227. if (all_csi_has_hastate_for_si (
  228. csi_assignment->si_assignment, SA_AMF_HA_STANDBY)) {
  229. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_STANDBY;
  230. }
  231. if (any_csi_has_hastate_in_su (
  232. csi_assignment->comp->su, SA_AMF_HA_QUIESCING)) {
  233. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_QUIESCING;
  234. }
  235. if (any_csi_has_hastate_in_su (
  236. csi_assignment->comp->su, SA_AMF_HA_QUIESCED)) {
  237. csi_assignment->si_assignment->saAmfSISUHAState = SA_AMF_HA_QUIESCED;
  238. }
  239. /* log changes to HA state */
  240. if (old_ha_state != csi_assignment->si_assignment->saAmfSISUHAState) {
  241. log_printf (LOG_NOTICE, "SU HA state changed to '%s' for:\n"
  242. "\t\tSI '%s', SU '%s'",
  243. amf_ha_state (csi_assignment->si_assignment->saAmfSISUHAState),
  244. csi_assignment->si_assignment->si->name.value,
  245. csi_assignment->si_assignment->name.value);
  246. }
  247. /* log changes to assignment state */
  248. if (old_assigment_state !=
  249. amf_si_get_saAmfSIAssignmentState (csi_assignment->csi->si)) {
  250. log_printf (LOG_NOTICE, "SI Assignment state changed to '%s' for:\n"
  251. "\t\tSI '%s', SU '%s'",
  252. amf_assignment_state (
  253. amf_si_get_saAmfSIAssignmentState (csi_assignment->csi->si)),
  254. csi_assignment->si_assignment->si->name.value,
  255. csi_assignment->si_assignment->name.value);
  256. }
  257. }
  258. char *amf_csi_dn_make (struct amf_csi *csi, SaNameT *name)
  259. {
  260. int i = snprintf((char*) name->value, SA_MAX_NAME_LENGTH,
  261. "safCsi=%s,safSi=%s,safApp=%s",
  262. csi->name.value, csi->si->name.value,
  263. csi->si->application->name.value);
  264. assert (i <= SA_MAX_NAME_LENGTH);
  265. name->length = i;
  266. return(char *)name->value;
  267. }
  268. void amf_si_comp_set_ha_state_done (
  269. struct amf_si *si, struct amf_csi_assignment *csi_assignment)
  270. {
  271. ENTER ("'%s', '%s'", si->name.value, csi_assignment->csi->name.value);
  272. set_si_ha_state (csi_assignment);
  273. assert (csi_assignment->si_assignment->assumed_callback_fn != NULL);
  274. /*
  275. * Report to caller when the requested SI assignment state is
  276. * confirmed.
  277. */
  278. if (csi_assignment->si_assignment->requested_ha_state ==
  279. csi_assignment->si_assignment->saAmfSISUHAState) {
  280. TRACE1("'%s', '%s'", si->name.value, csi_assignment->csi->name.value);
  281. csi_assignment->si_assignment->assumed_callback_fn (
  282. csi_assignment->si_assignment, 0);
  283. csi_assignment->si_assignment->assumed_callback_fn = NULL;
  284. }
  285. }
  286. void amf_si_activate (
  287. struct amf_si *si,
  288. void (*activated_callback_fn)(struct amf_si *si, int result))
  289. {
  290. struct amf_csi *csi;
  291. ENTER ("'%s'", si->name.value);
  292. for (csi = si->csi_head; csi != NULL; csi = csi->next) {
  293. struct amf_csi_assignment *csi_assignment;
  294. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  295. csi_assignment = csi_assignment->next) {
  296. csi_assignment->si_assignment->requested_ha_state =
  297. SA_AMF_HA_ACTIVE;
  298. /*
  299. * TODO: only active assignments should be set when dependency
  300. * levels are used.
  301. */
  302. csi_assignment->requested_ha_state = SA_AMF_HA_ACTIVE;
  303. amf_comp_hastate_set (csi_assignment->comp, csi_assignment);
  304. }
  305. }
  306. }
  307. void amf_si_comp_set_ha_state_failed (
  308. struct amf_si *si, struct amf_csi_assignment *csi_assignment)
  309. {
  310. ENTER ("");
  311. assert (0);
  312. }
  313. static void timer_function_ha_state_assumed (void *_si_assignment)
  314. {
  315. struct amf_si_assignment *si_assignment = _si_assignment;
  316. ENTER ("");
  317. si_assignment->saAmfSISUHAState = si_assignment->requested_ha_state;
  318. si_assignment->assumed_callback_fn (si_assignment, 0);
  319. }
  320. void amf_si_ha_state_assume (
  321. struct amf_si_assignment *si_assignment,
  322. void (*assumed_ha_state_callback_fn)(struct amf_si_assignment *si_assignment,
  323. int result))
  324. {
  325. struct amf_csi_assignment *csi_assignment;
  326. struct amf_csi *csi;
  327. int csi_assignment_cnt = 0;
  328. int hastate_set_done_cnt = 0;
  329. ENTER ("SI '%s' SU '%s' state %s", si_assignment->si->name.value,
  330. si_assignment->su->name.value,
  331. amf_ha_state (si_assignment->requested_ha_state));
  332. si_assignment->assumed_callback_fn = assumed_ha_state_callback_fn;
  333. for (csi = si_assignment->si->csi_head; csi != NULL; csi = csi->next) {
  334. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  335. csi_assignment = csi_assignment->next) {
  336. /*
  337. * If the CSI assignment and the SI assignment belongs to the
  338. * same SU, we have a match and can request the component to
  339. * change HA state.
  340. */
  341. if (name_match (&csi_assignment->comp->su->name,
  342. &si_assignment->su->name) &&
  343. (csi_assignment->saAmfCSICompHAState !=
  344. si_assignment->requested_ha_state)) {
  345. csi_assignment_cnt++;
  346. csi_assignment->requested_ha_state =
  347. si_assignment->requested_ha_state;
  348. amf_comp_hastate_set (csi_assignment->comp, csi_assignment);
  349. if (csi_assignment->saAmfCSICompHAState ==
  350. csi_assignment->requested_ha_state) {
  351. hastate_set_done_cnt++;
  352. }
  353. }
  354. }
  355. }
  356. /*
  357. * If the SU has only one component which is the faulty one, we
  358. * will not get an asynchronous response from the component.
  359. * This response (amf_si_comp_set_ha_state_done) is used to do
  360. * the next state transition. The asynchronous response is
  361. * simulated using a timeout instead.
  362. */
  363. if (csi_assignment_cnt == hastate_set_done_cnt) {
  364. poll_timer_handle handle;
  365. poll_timer_add (aisexec_poll_handle, 0, si_assignment,
  366. timer_function_ha_state_assumed, &handle);
  367. }
  368. }
  369. /**
  370. * Get number of active assignments for the specified SI
  371. * @param si
  372. *
  373. * @return int
  374. */
  375. int amf_si_get_saAmfSINumCurrActiveAssignments (struct amf_si *si)
  376. {
  377. int cnt = 0;
  378. struct amf_si_assignment *si_assignment;
  379. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  380. si_assignment = si_assignment->next) {
  381. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  382. cnt++;
  383. }
  384. }
  385. return cnt;
  386. }
  387. int amf_si_su_get_saAmfSINumCurrActiveAssignments (struct amf_si *si,
  388. struct amf_su *su)
  389. {
  390. int cnt = 0;
  391. struct amf_si_assignment *si_assignment;
  392. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  393. si_assignment = si_assignment->next) {
  394. if (si_assignment->su == su &&
  395. si_assignment->saAmfSISUHAState == SA_AMF_HA_ACTIVE) {
  396. cnt++;
  397. }
  398. }
  399. return cnt;
  400. }
  401. int amf_si_get_saAmfSINumCurrStandbyAssignments (struct amf_si *si)
  402. {
  403. int cnt = 0;
  404. struct amf_si_assignment *si_assignment;
  405. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  406. si_assignment = si_assignment->next) {
  407. if (si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  408. cnt++;
  409. }
  410. }
  411. return cnt;
  412. }
  413. int amf_si_su_get_saAmfSINumCurrStandbyAssignments (struct amf_si *si,
  414. struct amf_su *su)
  415. {
  416. int cnt = 0;
  417. struct amf_si_assignment *si_assignment;
  418. for (si_assignment = si->assigned_sis; si_assignment != NULL;
  419. si_assignment = si_assignment->next) {
  420. if (si_assignment->su == su &&
  421. si_assignment->saAmfSISUHAState == SA_AMF_HA_STANDBY) {
  422. cnt++;
  423. }
  424. }
  425. return cnt;
  426. }
  427. SaAmfAssignmentStateT amf_si_get_saAmfSIAssignmentState (struct amf_si *si)
  428. {
  429. if ((amf_si_get_saAmfSINumCurrActiveAssignments (si) ==
  430. si->saAmfSIPrefActiveAssignments) &&
  431. (amf_si_get_saAmfSINumCurrStandbyAssignments (si) ==
  432. si->saAmfSIPrefStandbyAssignments)) {
  433. return SA_AMF_ASSIGNMENT_FULLY_ASSIGNED;
  434. } else if (amf_si_get_saAmfSINumCurrActiveAssignments (si) == 0) {
  435. return SA_AMF_ASSIGNMENT_UNASSIGNED;
  436. } else {
  437. return SA_AMF_ASSIGNMENT_PARTIALLY_ASSIGNED;
  438. }
  439. }
  440. void amf_csi_delete_assignments (struct amf_csi *csi, struct amf_su *su)
  441. {
  442. struct amf_csi_assignment *csi_assignment;
  443. ENTER ("'%s'", su->name.value);
  444. struct amf_csi_assignment **prev = &csi->assigned_csis;
  445. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  446. csi_assignment = csi_assignment->next) {
  447. if (csi_assignment->comp->su == su) {
  448. struct amf_csi_assignment *tmp = csi_assignment;
  449. *prev = csi_assignment->next;
  450. dprintf ("CSI assignment %s unlinked", tmp->name.value);
  451. free (tmp);
  452. } else {
  453. prev = &csi_assignment->next;
  454. }
  455. }
  456. }
  457. /**
  458. * Constructor for SI objects. Adds SI last in the ordered
  459. * list owned by the specified application. Always returns a
  460. * valid SI object, out-of-memory problems are handled here.
  461. * Default values are initialized.
  462. * @param app
  463. *
  464. * @return struct amf_si*
  465. */
  466. struct amf_si *amf_si_new (struct amf_application *app, char *name)
  467. {
  468. struct amf_si *tail = app->si_head;
  469. struct amf_si *si = amf_calloc (1, sizeof (struct amf_si));
  470. while (tail != NULL) {
  471. if (tail->next == NULL) {
  472. break;
  473. }
  474. tail = tail->next;
  475. }
  476. if (tail == NULL) {
  477. app->si_head = si;
  478. } else {
  479. tail->next = si;
  480. }
  481. si->application = app;
  482. /* setup default values from spec. */
  483. si->saAmfSIAdminState = SA_AMF_ADMIN_UNLOCKED;
  484. si->saAmfSIRank = 0;
  485. si->saAmfSIPrefActiveAssignments = 1;
  486. si->saAmfSIPrefStandbyAssignments = 1;
  487. si->assigned_sis = NULL;
  488. si->csi_head = NULL;
  489. setSaNameT (&si->name, name);
  490. return si;
  491. }
  492. void amf_si_delete (struct amf_si *si)
  493. {
  494. struct amf_si_assignment *si_assignment;
  495. struct amf_csi *csi;
  496. for (csi = si->csi_head; csi != NULL;) {
  497. struct amf_csi *tmp = csi;
  498. csi = csi->next;
  499. amf_csi_delete (tmp);
  500. }
  501. for (si_assignment = si->assigned_sis; si_assignment != NULL;) {
  502. struct amf_si_assignment *tmp = si_assignment;
  503. si_assignment = si_assignment->next;
  504. free (tmp);
  505. }
  506. free (si);
  507. }
  508. void *amf_si_serialize (struct amf_si *si, int *len)
  509. {
  510. char *buf = NULL;
  511. int offset = 0, size = 0;
  512. TRACE8 ("%s", si->name.value);
  513. buf = amf_serialize_SaNameT (buf, &size, &offset, &si->name);
  514. buf = amf_serialize_SaNameT (buf, &size, &offset,
  515. &si->saAmfSIProtectedbySG);
  516. buf = amf_serialize_SaUint32T (buf, &size, &offset, si->saAmfSIRank);
  517. buf = amf_serialize_SaUint32T (buf, &size, &offset, si->saAmfSINumCSIs);
  518. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  519. si->saAmfSIPrefActiveAssignments);
  520. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  521. si->saAmfSIPrefStandbyAssignments);
  522. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  523. si->saAmfSIAdminState);
  524. *len = offset;
  525. return buf;
  526. }
  527. struct amf_si *amf_si_deserialize (struct amf_application *app, char *buf)
  528. {
  529. char *tmp = buf;
  530. struct amf_si *si = amf_si_new (app, "");
  531. tmp = amf_deserialize_SaNameT (tmp, &si->name);
  532. tmp = amf_deserialize_SaNameT (tmp, &si->saAmfSIProtectedbySG);
  533. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIRank);
  534. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSINumCSIs);
  535. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIPrefActiveAssignments);
  536. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIPrefStandbyAssignments);
  537. tmp = amf_deserialize_SaUint32T (tmp, &si->saAmfSIAdminState);
  538. return si;
  539. }
  540. /*****************************************************************************
  541. * SI Assignment class implementation *
  542. ****************************************************************************/
  543. struct amf_si_assignment *amf_si_assignment_new (struct amf_si *si)
  544. {
  545. struct amf_si_assignment *si_assignment =
  546. amf_calloc (1, sizeof (struct amf_si_assignment));
  547. si_assignment->si = si;
  548. si_assignment->next = si->assigned_sis;
  549. si->assigned_sis = si_assignment;
  550. return si_assignment;
  551. }
  552. void *amf_si_assignment_serialize (
  553. amf_si_assignment_t *si_assignment, int *len)
  554. {
  555. char *buf = NULL;
  556. int offset = 0, size = 0;
  557. TRACE8 ("%s", si_assignment->name.value);
  558. buf = amf_serialize_SaNameT (buf, &size, &offset, &si_assignment->name);
  559. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  560. si_assignment->saAmfSISUHAState);
  561. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  562. si_assignment->requested_ha_state);
  563. *len = offset;
  564. return buf;
  565. }
  566. struct amf_si_assignment *amf_si_assignment_deserialize (
  567. struct amf_si *si, char *buf)
  568. {
  569. char *tmp = buf;
  570. struct amf_si_assignment *si_assignment = amf_si_assignment_new (si);
  571. tmp = amf_deserialize_SaNameT (tmp, &si_assignment->name);
  572. tmp = amf_deserialize_SaUint32T (tmp, &si_assignment->saAmfSISUHAState);
  573. tmp = amf_deserialize_SaUint32T (tmp, &si_assignment->requested_ha_state);
  574. si_assignment->su = amf_su_find (si->application->cluster,
  575. &si_assignment->name);
  576. return si_assignment;
  577. }
  578. struct amf_si *amf_si_find (struct amf_application *app, char *name)
  579. {
  580. struct amf_si *si;
  581. for (si = app->si_head; si != NULL; si = si->next) {
  582. if (si->name.length == strlen(name) &&
  583. strncmp (name, (char*)si->name.value, si->name.length) == 0) {
  584. break;
  585. }
  586. }
  587. if (si == NULL) {
  588. dprintf ("SI %s not found!", name);
  589. }
  590. return si;
  591. }
  592. /*****************************************************************************
  593. * CSI class implementation *
  594. ****************************************************************************/
  595. struct amf_csi *amf_csi_new (struct amf_si *si)
  596. {
  597. struct amf_csi *csi = amf_calloc (1, sizeof (struct amf_csi));
  598. csi->si = si;
  599. csi->next = si->csi_head;
  600. si->csi_head = csi;
  601. return csi;
  602. }
  603. void amf_csi_delete (struct amf_csi *csi)
  604. {
  605. struct amf_csi_assignment *csi_assignment;
  606. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;) {
  607. struct amf_csi_assignment *tmp = csi_assignment;
  608. csi_assignment = csi_assignment->next;
  609. free (tmp);
  610. }
  611. free (csi);
  612. }
  613. void *amf_csi_serialize (struct amf_csi *csi, int *len)
  614. {
  615. char *buf = NULL;
  616. int offset = 0, size = 0;
  617. TRACE8 ("%s", csi->name.value);
  618. buf = amf_serialize_SaNameT (buf, &size, &offset, &csi->name);
  619. buf = amf_serialize_SaNameT (buf, &size, &offset, &csi->saAmfCSTypeName);
  620. *len = offset;
  621. return buf;
  622. }
  623. struct amf_csi *amf_csi_deserialize (struct amf_si *si, char *buf)
  624. {
  625. char *tmp = buf;
  626. struct amf_csi *csi = amf_csi_new (si);
  627. tmp = amf_deserialize_SaNameT (tmp, &csi->name);
  628. tmp = amf_deserialize_SaNameT (tmp, &csi->saAmfCSTypeName);
  629. return csi;
  630. }
  631. struct amf_csi *amf_csi_find (struct amf_si *si, char *name)
  632. {
  633. struct amf_csi *csi;
  634. for (csi = si->csi_head; csi != NULL; csi = csi->next) {
  635. if (csi->name.length == strlen(name) &&
  636. strncmp (name, (char*)csi->name.value, csi->name.length) == 0) {
  637. break;
  638. }
  639. }
  640. if (csi == NULL) {
  641. dprintf ("CSI %s not found!", name);
  642. }
  643. return csi;
  644. }
  645. /*****************************************************************************
  646. * CSI Assignment class implementation *
  647. ****************************************************************************/
  648. struct amf_csi_assignment *amf_csi_assignment_new (struct amf_csi *csi)
  649. {
  650. struct amf_csi_assignment *csi_assignment =
  651. amf_calloc (1, sizeof (struct amf_csi_assignment));
  652. csi_assignment->csi = csi;
  653. csi_assignment->next = csi->assigned_csis;
  654. csi->assigned_csis = csi_assignment;
  655. return csi_assignment;
  656. }
  657. void *amf_csi_assignment_serialize (
  658. struct amf_csi_assignment *csi_assignment, int *len)
  659. {
  660. char *buf = NULL;
  661. int offset = 0, size = 0;
  662. TRACE8 ("%s", csi_assignment->name.value);
  663. buf = amf_serialize_SaNameT (buf, &size, &offset, &csi_assignment->name);
  664. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  665. csi_assignment->saAmfCSICompHAState);
  666. buf = amf_serialize_SaUint32T (buf, &size, &offset,
  667. csi_assignment->requested_ha_state);
  668. *len = offset;
  669. return buf;
  670. }
  671. struct amf_si_assignment *si_assignment_find (
  672. struct amf_csi_assignment *csi_assignment)
  673. {
  674. struct amf_comp *component;
  675. struct amf_si_assignment *si_assignment = NULL;
  676. component = amf_comp_find(csi_assignment->csi->si->application->cluster,
  677. &csi_assignment->name);
  678. for (si_assignment = csi_assignment->csi->si->assigned_sis;
  679. si_assignment != NULL; si_assignment = si_assignment->next) {
  680. SaNameT su_name;
  681. amf_su_dn_make (component->su,&su_name);
  682. if (name_match(&su_name, &si_assignment->name)) {
  683. break;
  684. }
  685. }
  686. return si_assignment;
  687. }
  688. struct amf_csi_assignment *amf_csi_assignment_deserialize (
  689. struct amf_csi *csi, char *buf)
  690. {
  691. char *tmp = buf;
  692. struct amf_csi_assignment *csi_assignment = amf_csi_assignment_new (csi);
  693. tmp = amf_deserialize_SaNameT (tmp, &csi_assignment->name);
  694. tmp = amf_deserialize_SaUint32T (tmp,
  695. &csi_assignment->saAmfCSICompHAState);
  696. tmp = amf_deserialize_SaUint32T (tmp, &csi_assignment->requested_ha_state);
  697. csi_assignment->comp = amf_comp_find (csi->si->application->cluster,
  698. &csi_assignment->name);
  699. assert (csi_assignment->comp != NULL);
  700. csi_assignment->si_assignment = si_assignment_find(csi_assignment);
  701. return csi_assignment;
  702. }
  703. char *amf_csi_assignment_dn_make (
  704. struct amf_csi_assignment *csi_assignment, SaNameT *name)
  705. {
  706. SaNameT comp_name;
  707. struct amf_csi *csi = csi_assignment->csi;
  708. int i;
  709. amf_comp_dn_make (csi_assignment->comp, &comp_name);
  710. i = snprintf((char*) name->value, SA_MAX_NAME_LENGTH,
  711. "safCSIComp=%s,safCsi=%s,safSi=%s,safApp=%s",
  712. comp_name.value,
  713. csi->name.value, csi->si->name.value,
  714. csi->si->application->name.value);
  715. assert (i <= SA_MAX_NAME_LENGTH);
  716. name->length = i;
  717. return(char *)name->value;
  718. }
  719. struct amf_csi_assignment *amf_csi_assignment_find (
  720. struct amf_cluster *cluster, SaNameT *name)
  721. {
  722. struct amf_application *app;
  723. struct amf_si *si;
  724. struct amf_csi *csi;
  725. struct amf_csi_assignment *csi_assignment = NULL;
  726. char *app_name;
  727. char *si_name;
  728. char *csi_name;
  729. char *csi_assignment_name;
  730. char *buf;
  731. /* malloc new buffer since we need to write to the buffer */
  732. buf = amf_malloc (name->length + 1);
  733. memcpy (buf, name->value, name->length + 1);
  734. csi_assignment_name = strstr (buf, "safCSIComp=");
  735. csi_name = strstr (buf, "safCsi=");
  736. si_name = strstr (buf, "safSi=");
  737. app_name = strstr (buf, "safApp=");
  738. app_name++;
  739. app_name = strstr (app_name, "safApp=");
  740. if (csi_assignment_name == NULL || csi_name == NULL || si_name == NULL ||
  741. app_name == NULL) {
  742. goto end;
  743. }
  744. *(csi_name - 1) = '\0';
  745. *(si_name - 1) = '\0';
  746. *(app_name - 1) = '\0';
  747. /* jump to value */
  748. csi_assignment_name += 11;
  749. csi_name += 7;
  750. si_name += 6;
  751. app_name += 7;
  752. app = amf_application_find (cluster, app_name);
  753. if (app == NULL) {
  754. goto end;
  755. }
  756. si = amf_si_find (app, si_name);
  757. if (si == NULL) {
  758. goto end;
  759. }
  760. csi = amf_csi_find (si, csi_name);
  761. if (csi == NULL) {
  762. goto end;
  763. }
  764. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  765. csi_assignment = csi_assignment->next) {
  766. if (csi_assignment->name.length == strlen(csi_assignment_name) &&
  767. strncmp (csi_assignment_name,
  768. (char*)csi_assignment->name.value,
  769. csi_assignment->name.length) == 0) {
  770. goto end;
  771. }
  772. }
  773. end:
  774. assert(csi_assignment);
  775. free (buf);
  776. return csi_assignment;
  777. }
  778. struct amf_csi_attribute *amf_csi_attribute_new (struct amf_csi *csi)
  779. {
  780. struct amf_csi_attribute *csi_attribute =
  781. amf_calloc (1, sizeof (struct amf_csi_assignment));
  782. csi_attribute->next = csi->attributes_head;
  783. csi->attributes_head = csi_attribute;
  784. return csi_attribute;
  785. }
  786. void *amf_csi_attribute_serialize (
  787. struct amf_csi_attribute *csi_attribute, int *len)
  788. {
  789. char *buf = NULL;
  790. int i, offset = 0, size = 0;
  791. TRACE8 ("%s", csi_attribute->name);
  792. buf = amf_serialize_SaStringT (buf, &size, &offset, csi_attribute->name);
  793. /* count value and write to buf */
  794. for (i = 0; csi_attribute->value &&
  795. csi_attribute->value[i] != NULL; i++);
  796. buf = amf_serialize_SaUint32T (buf, &size, &offset, i);
  797. for (i = 0; csi_attribute->value &&
  798. csi_attribute->value[i] != NULL; i++) {
  799. buf = amf_serialize_SaStringT (
  800. buf, &size, &offset, csi_attribute->value[i]);
  801. }
  802. *len = offset;
  803. return buf;
  804. }
  805. struct amf_csi_attribute *amf_csi_attribute_deserialize (
  806. struct amf_csi *csi, char *buf)
  807. {
  808. char *tmp = buf;
  809. struct amf_csi_attribute *csi_attribute;
  810. int i;
  811. SaUint32T cnt;
  812. csi_attribute = amf_csi_attribute_new (csi);
  813. tmp = amf_deserialize_SaStringT (tmp, &csi_attribute->name);
  814. tmp = amf_deserialize_SaUint32T (tmp, &cnt);
  815. csi_attribute->value = amf_malloc ((cnt + 1) * sizeof (SaStringT*));
  816. for (i = 0; i < cnt; i++) {
  817. tmp = amf_deserialize_SaStringT (tmp, &csi_attribute->value[i]);
  818. }
  819. csi_attribute->value[i] = NULL;
  820. return csi_attribute;
  821. }
  822. void amf_si_assignment_remove (amf_si_assignment_t *si_assignment,
  823. async_func_t async_func)
  824. {
  825. struct amf_csi_assignment *csi_assignment;
  826. struct amf_csi *csi;
  827. int csi_assignment_cnt = 0;
  828. ENTER ("SI '%s' SU '%s' state %s", si_assignment->si->name.value,
  829. si_assignment->su->name.value,
  830. amf_ha_state (si_assignment->requested_ha_state));
  831. si_assignment->requested_ha_state = USR_AMF_HA_STATE_REMOVED;
  832. si_assignment->removed_callback_fn = async_func;
  833. for (csi = si_assignment->si->csi_head; csi != NULL; csi = csi->next) {
  834. for (csi_assignment = csi->assigned_csis; csi_assignment != NULL;
  835. csi_assignment = csi_assignment->next) {
  836. /*
  837. * If the CSI assignment and the SI assignment belongs to the
  838. * same SU, we have a match and can request the component to
  839. * remove the CSI.
  840. */
  841. if (name_match (&csi_assignment->comp->su->name,
  842. &si_assignment->su->name)) {
  843. csi_assignment_cnt++;
  844. csi_assignment->requested_ha_state = USR_AMF_HA_STATE_REMOVED;
  845. amf_comp_csi_remove (csi_assignment->comp, csi_assignment);
  846. }
  847. }
  848. }
  849. /*
  850. * If the SU has only one component which is the faulty one, we
  851. * will not get an asynchronous response from the component.
  852. * This response (amf_si_comp_set_ha_state_done) is used to do
  853. * the next state transition. The asynchronous response is
  854. * simulated using a timeout instead.
  855. */
  856. if (csi_assignment_cnt == 0) {
  857. amf_call_function_asynchronous (async_func, si_assignment);
  858. }
  859. }
  860. void amf_si_comp_csi_removed (
  861. struct amf_si *si, struct amf_csi_assignment *csi_assignment,
  862. SaAisErrorT error)
  863. {
  864. ENTER ("'%s', '%s'", si->name.value, csi_assignment->csi->name.value);
  865. assert (csi_assignment->si_assignment->removed_callback_fn != NULL);
  866. csi_assignment->saAmfCSICompHAState = USR_AMF_HA_STATE_REMOVED;
  867. /*
  868. * Report to caller when all requested CSI assignments has
  869. * been removed.
  870. */
  871. if (all_csi_assignments_removed(csi_assignment->si_assignment)) {
  872. csi_assignment->si_assignment->removed_callback_fn (
  873. csi_assignment->si_assignment);
  874. }
  875. }