amfsi.c 30 KB

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