Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

749 lines
15 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. gs.c
  5. Abstract:
  6. Creation and deletion of groups
  7. Author:
  8. Ahmed Mohamed (ahmedm) 12, 01, 2000
  9. Revision History:
  10. --*/
  11. #include "gs.h"
  12. #include "gsp.h"
  13. #include <stdio.h>
  14. extern void ConfigInit();
  15. extern gs_nid_t GsLocalNodeId;
  16. extern int GsMaxNodeId;
  17. extern int GsMinNodeId;
  18. void cm_init();
  19. void cm_start();
  20. gs_group_t GsGroupTable[GsGroupTableSize];
  21. HANDLE ns_gd;
  22. HANDLE
  23. WINAPI
  24. GsGetGroupHandle(HANDLE msgd)
  25. {
  26. gs_msg_t *msg = (gs_msg_t *)msgd;
  27. return (HANDLE) &GsGroupTable[msg->m_hdr.h_gid];
  28. }
  29. int
  30. WINAPI
  31. GsGetSourceMemberid(HANDLE msgd)
  32. {
  33. gs_msg_t *msg = (gs_msg_t *)msgd;
  34. return (int) msg->m_hdr.h_sid;
  35. }
  36. void
  37. GspInitGroup(gs_group_t *gd, int wsz);
  38. // Internal routines
  39. gs_group_t *
  40. GspLookupGroup(gs_gid_t gid)
  41. {
  42. gs_group_t *gd;
  43. if (gid >= GsGroupTableSize) {
  44. return NULL;
  45. }
  46. gd = &GsGroupTable[gid];
  47. assert(gd->g_id == gid);
  48. if (gd->g_state == GS_GROUP_STATE_FREE ||
  49. gd->g_state == GS_GROUP_STATE_NEW) {
  50. return NULL;
  51. }
  52. assert(gd->g_state != GS_GROUP_STATE_FREE);
  53. return gd;
  54. }
  55. gs_group_t *
  56. GspLookupGroupByName(char *name, int len)
  57. {
  58. gs_group_t *gd;
  59. int i;
  60. for (i = 0; i < GsGroupTableSize; i++) {
  61. gd = &GsGroupTable[i];
  62. if (gd->g_state != GS_GROUP_STATE_FREE &&
  63. len == gd->g_namelen && !strcmp(gd->g_name, name)) {
  64. return gd;
  65. }
  66. }
  67. return NULL;
  68. }
  69. gs_group_t *
  70. GspAllocateGroup(char *name, int len)
  71. {
  72. int i;
  73. for (i = 0; i < GsGroupTableSize; i++) {
  74. gs_group_t *gd;
  75. gd = &GsGroupTable[i];
  76. if (gd->g_state == GS_GROUP_STATE_FREE) {
  77. // set everything to zero
  78. memset(gd, 0, sizeof(*gd));
  79. gd->g_id = i;
  80. gd->g_nid = GsLocalNodeId;
  81. GsLockInit(gd->g_lock);
  82. gd->g_name = name;
  83. gd->g_namelen = len;
  84. gd->g_state = GS_GROUP_STATE_NEW;
  85. return gd;
  86. }
  87. }
  88. return NULL;
  89. }
  90. void
  91. GspDeleteGroup(gs_group_t *gd)
  92. {
  93. // xxx: grab lock in write mode
  94. assert(gd->g_state != GS_GROUP_STATE_FREE);
  95. if (gd->g_name) {
  96. free(gd->g_name);
  97. }
  98. gd->g_name = NULL;
  99. gd->g_namelen = 0;
  100. gd->g_mset = 0;
  101. gd->g_state = GS_GROUP_STATE_FREE;
  102. if (gd->g_mlist) {
  103. free((char *) gd->g_mlist);
  104. }
  105. if (gd->g_send.s_ctxpool) {
  106. free((char *) gd->g_send.s_ctxpool);
  107. }
  108. // xxx: drop lock
  109. }
  110. void
  111. GspAddMember(gs_group_t *gd, gs_memberid_t mid, int wsz)
  112. {
  113. gs_member_t *p;
  114. ns_log(("Add member gid %d sz %d mid %d\n",
  115. gd->g_id, gd->g_sz, mid));
  116. p = (gs_member_t *) malloc(sizeof(gs_member_t) * (gd->g_sz+1));
  117. if (p == NULL) {
  118. err_log(("Unable to extend member table\n"));
  119. exit(1);
  120. }
  121. if (gd->g_mlist) {
  122. memcpy(p, gd->g_mlist, sizeof(gs_member_t) * (gd->g_sz));
  123. free((char *)gd->g_mlist);
  124. }
  125. gd->g_mlist = p;
  126. gd->g_mset |= (1 << mid);
  127. p += gd->g_sz;
  128. gd->g_sz++;
  129. gd->g_curview++;
  130. // init member state
  131. p->m_id = gd->g_sz;
  132. p->m_expected_seq = 0;
  133. p->m_wsz = (UINT16) wsz;
  134. p->m_msz = (UINT16) GS_DEFAULT_MAX_MSG_SZ;
  135. }
  136. void
  137. GspSetMaster(gs_group_t *gd, gs_memberid_t mid)
  138. {
  139. gd->g_mid = mid;
  140. }
  141. void
  142. GspInitGroup(gs_group_t *gd, int wsz)
  143. {
  144. int i;
  145. // init send state
  146. GsSemaInit(gd->g_send.s_sema, wsz);
  147. gd->g_send.s_wsz = (UINT16) wsz;
  148. // allocate window size contexts
  149. gd->g_send.s_ctxpool = (gs_context_t *) malloc(sizeof(gs_context_t) * wsz);
  150. if (gd->g_send.s_ctxpool == NULL) {
  151. assert(0);
  152. }
  153. for (i = 0; i < wsz; i++) {
  154. gs_context_t *p = &gd->g_send.s_ctxpool[i];
  155. p->ctx_id = GS_CONTEXT_INVALID_ID;
  156. p->ctx_gid = gd->g_id;
  157. p->ctx_buf = 0;
  158. p->ctx_rbuf = 0;
  159. p->ctx_msg = 0;
  160. p->ctx_event = 0;
  161. GsEventInit(p->ctx_syncevent);
  162. }
  163. // init receive state
  164. gd->g_recv.r_next = &gd->g_recv.r_head;
  165. }
  166. void
  167. WINAPI
  168. GsInit()
  169. {
  170. int i;
  171. void NsForm();
  172. void NsJoin();
  173. timeBeginPeriod(50);
  174. ConfigInit();
  175. // Initialize global data structure
  176. for (i = 0; i < GsGroupTableSize; i++) {
  177. gs_group_t *gd;
  178. gd = &GsGroupTable[i];
  179. gd->g_state = GS_GROUP_STATE_FREE;
  180. gd->g_mset = 0;
  181. }
  182. // init and start connection manager
  183. cm_init();
  184. NsForm();
  185. cm_start();
  186. NsJoin();
  187. }
  188. void
  189. WINAPI
  190. GsExit()
  191. {
  192. int i;
  193. // stop messaging
  194. msg_exit();
  195. // free context pool and membership list for each group in group table
  196. for (i = 0; i < GsGroupTableSize; i++) {
  197. gs_group_t *gd;
  198. gd = &GsGroupTable[i];
  199. GspDeleteGroup(gd);
  200. }
  201. timeEndPeriod(50);
  202. }
  203. #define NS_TABLE_READ 0
  204. #define NS_TABLE_ADD 1
  205. HANDLE
  206. WINAPI
  207. GsCreateGroup(gs_callback_t func, char *name, int len, int wsz,
  208. int disposition, HANDLE *join_ctx)
  209. {
  210. gs_group_t *gd;
  211. PVOID io[GS_MAX_GROUP_SZ];
  212. int result[GS_MAX_GROUP_SZ];
  213. int i;
  214. NTSTATUS err;
  215. IO_STATUS_BLOCK status[GS_MAX_GROUP_SZ];
  216. gs_ns_info_t info;
  217. int GspJoin(HANDLE group, gs_event_t event, PVOID io[], IO_STATUS_BLOCK status[],
  218. int wsz, HANDLE *context);
  219. gs_event_t event;
  220. union {
  221. int cmd;
  222. gs_tag_t tag;
  223. }tag;
  224. if (name == NULL || len > GS_MAX_NAME_SZ) {
  225. return NULL;
  226. }
  227. ns_log(("Create group %s\n", name));
  228. for (i = 0; i < GS_MAX_GROUP_SZ; i++) {
  229. status[i].Information = 0;
  230. io[i] = (PVOID)&result[i];
  231. result[i] = TRUE;
  232. }
  233. // Based on disposition we either form or join
  234. info.owner = (USHORT) ((gs_group_t *)ns_gd)->g_nid;
  235. info.wsz = (UINT16) wsz;
  236. strcpy(info.name, name);
  237. GsEventInit(event);
  238. retry:
  239. tag.cmd = NS_TABLE_ADD;
  240. err = GsSendDeliveredRequest(ns_gd, event,
  241. tag.tag, (PVOID) &info, sizeof(info),
  242. io, sizeof(result[0]),
  243. status,
  244. NULL);
  245. if (err != ERROR_SUCCESS) {
  246. GsEventFree(event);
  247. err_log(("Create group failed %d\n", err));
  248. return NULL;
  249. }
  250. // xxx: make sure result is true
  251. gd = GspLookupGroupByName(name, len);
  252. if (gd != NULL) {
  253. int err;
  254. ns_log(("Init group %x\n", gd));
  255. GspInitGroup(gd, wsz);
  256. GsRegisterHandler((HANDLE)gd, func);
  257. err = GspJoin((HANDLE) gd, event, io, status, wsz, join_ctx);
  258. if (err) {
  259. ns_log(("Init group gspjoin failed, need to retry\n"));
  260. goto retry;
  261. }
  262. }
  263. ns_log(("Created group %x\n", gd));
  264. GsEventFree(event);
  265. return (HANDLE) gd;
  266. }
  267. NTSTATUS
  268. GsCloseGroup(HANDLE group)
  269. {
  270. gs_group_t *gd = (gs_group_t *)group;
  271. GspDeleteGroup(gd);
  272. return ERROR_SUCCESS;
  273. }
  274. void
  275. GsRegisterHandler(HANDLE group, gs_callback_t func)
  276. {
  277. gs_group_t *gd = (gs_group_t *) group;
  278. gd->g_callback = func;
  279. }
  280. NTSTATUS
  281. GsQueryGroup(HANDLE group, gs_info_t *info)
  282. {
  283. gs_group_t *gd;
  284. if (group == NULL) {
  285. group = ns_gd;
  286. }
  287. gd = (gs_group_t *) group;
  288. if (!gd || !info) {
  289. return ERROR_INVALID_PARAMETER;
  290. }
  291. info->lid = gd->g_nid;
  292. info->mid = gd->g_mid;
  293. info->group_size = gd->g_sz;
  294. info->cluster_size = msg_getsize();
  295. info->mset = gd->g_mset;
  296. return ERROR_SUCCESS;
  297. }
  298. // Name server
  299. NTSTATUS
  300. ns_callback(HANDLE group, gs_tag_t mtag, PVOID buf, IO_STATUS_BLOCK *ios)
  301. {
  302. gs_ns_info_t table[GS_MAX_GROUPS];
  303. int i, j, result;
  304. gs_group_t *gd = (gs_group_t *) group;
  305. NTSTATUS err;
  306. gs_ns_info_t *info;
  307. int tag = *((int *)mtag);
  308. switch(ios->Status) {
  309. case GsEventData:
  310. ns_log(("NsCallback Disposition %d\n", tag));
  311. switch(tag) {
  312. case NS_TABLE_READ:
  313. // only group table master reponse to reads
  314. if (GsGroupTable[0].g_mid == GsGroupTable[0].g_nid) {
  315. j = 0;
  316. for (i = 1; i < GsGroupTableSize; i++) {
  317. gd = &GsGroupTable[i];
  318. if (gd->g_state != GS_GROUP_STATE_FREE) {
  319. table[j].owner = gd->g_mid;
  320. table[j].id = (USHORT) i;
  321. strcpy(table[j].name, gd->g_name);
  322. j++;
  323. }
  324. }
  325. ns_log(("Sending table size %d\n", j));
  326. err = GsSendReply(group, (PVOID) table, sizeof(table[0]) * j, STATUS_SUCCESS);
  327. if (err != ERROR_SUCCESS) {
  328. printf("Failed to respond to table read ns\n");
  329. }
  330. }
  331. break;
  332. case NS_TABLE_ADD:
  333. info = (gs_ns_info_t *)buf;
  334. assert(ios->Information == sizeof(*info));
  335. // xxx: lock table
  336. gd = GspLookupGroupByName(info->name, strlen(info->name));
  337. if (gd == NULL) {
  338. char * strsave(char *s);
  339. gd = GspAllocateGroup(strsave(info->name), strlen(info->name));
  340. if (gd != NULL) {
  341. GspSetMaster(gd, info->owner);
  342. }
  343. ns_log(("Ns Created group %s id %d owner %d\n",
  344. info->name, gd->g_id, gd->g_mid));
  345. }
  346. // xxx: unlock table
  347. if (gd != NULL) {
  348. result = TRUE;
  349. } else {
  350. result = FALSE;
  351. }
  352. err = GsSendReply(group, (PVOID) &result, sizeof(result), STATUS_SUCCESS);
  353. if (err != ERROR_SUCCESS) {
  354. err_log(("Failed to respond to add ns\n"));
  355. }
  356. break;
  357. default:
  358. err_log(("Invalid ns opcode, %d\n", tag));
  359. exit(1);
  360. }
  361. break;
  362. case GsEventMemberJoin:
  363. ns_log(("NsCallback member join %d\n", tag));
  364. break;
  365. case GsEventMemberUp:
  366. ns_log(("NsCallback member up %d\n", tag));
  367. break;
  368. case GsEventMemberDown:
  369. ns_log(("NsCallback member down %d\n", tag));
  370. break;
  371. default:
  372. ns_log(("Ns invalid event %d\n", ios->Status));
  373. }
  374. return ERROR_SUCCESS;
  375. }
  376. void
  377. NsForm()
  378. {
  379. char *name = "Name server";
  380. ns_gd = (HANDLE) GspAllocateGroup(name, strlen(name));
  381. if (ns_gd == NULL) {
  382. err_log(("Unable to create name server group!\n"));
  383. exit(1);
  384. }
  385. GspInitGroup((gs_group_t *)ns_gd, 1);
  386. GsRegisterHandler(ns_gd, ns_callback);
  387. }
  388. void
  389. NsSetOwner(gs_nid_t nid)
  390. {
  391. gs_group_t *gd = (gs_group_t *) ns_gd;
  392. ns_log(("Name server: master %d\n", nid));
  393. GsLockEnter(gd->g_lock);
  394. GspSetMaster(gd, (gs_memberid_t)nid);
  395. if (gd->g_rs != NULL && gd->g_mid != gd->g_nid) {
  396. gd->g_rs->rs_mset = (1 << gd->g_nid) | (1 << gd->g_mid);
  397. }
  398. GsLockExit(gd->g_lock);
  399. }
  400. int
  401. GspJoin(HANDLE group, gs_event_t event, PVOID io[], IO_STATUS_BLOCK status[],
  402. int wsz, HANDLE *context)
  403. {
  404. // if we don't master the name server, we simply send a
  405. // join request to this group and receive a table of
  406. // group names and owners
  407. gs_join_info_t info;
  408. int table[GS_MAX_GROUP_SZ];
  409. gs_group_t *gd = (gs_group_t *) group;
  410. gs_context_t *ctx;
  411. gs_memberid_t mid;
  412. union {
  413. int mid;
  414. gs_tag_t tag;
  415. }tag;
  416. if (context) *context = NULL;
  417. while (TRUE) {
  418. int err, i;
  419. UINT32 sz, flags;
  420. gs_msg_hdr_t hdr;
  421. GsLockEnter(gd->g_lock);
  422. ns_log(("join group %s mid %d\n", gd->g_name, gd->g_mid));
  423. if ((mid = gd->g_mid) == gd->g_nid) {
  424. gs_msg_t msg;
  425. memset(&msg, 0, sizeof(msg));
  426. msg.m_hdr.h_type = GS_MSG_TYPE_UP;
  427. msg.m_buf = (char *) &wsz;
  428. *((gs_memberid_t *)msg.m_hdr.h_tag) = mid;
  429. msg.m_hdr.h_len = sizeof(wsz);
  430. msg.m_hdr.h_flags = GS_FLAGS_REPLY;
  431. msg.m_hdr.h_gid = gd->g_id;
  432. GspDeliverMsg(gd, &msg);
  433. gd->g_state = GS_GROUP_STATE_FORM;
  434. GsLockExit(gd->g_lock);
  435. break;
  436. }
  437. gd->g_state = GS_GROUP_STATE_JOIN;
  438. GsLockExit(gd->g_lock);
  439. GspOpenContext(gd, &ctx);
  440. io[0] = (PVOID) &info;
  441. status[0].Information = 0;
  442. tag.mid = gd->g_nid,
  443. err = GspSendDirectedRequest(gd, ctx, event, mid,
  444. tag.tag, NULL, 0,
  445. &io[0], sizeof(info),
  446. &status[0],
  447. GS_FLAGS_DELIVERED,
  448. GS_MSG_TYPE_JOIN_REQUEST);
  449. GsLockEnter(gd->g_lock);
  450. if (gd->g_mid != mid) {
  451. GsLockExit(gd->g_lock);
  452. GspCloseContext(gd, ctx);
  453. continue;
  454. }
  455. if (err != ERROR_SUCCESS) {
  456. err_log(("Join failed %d\n", err));
  457. return 1;
  458. }
  459. if (status[0].Information != sizeof(info)) {
  460. err_log(("GspJoin: invalid returned size %d\n",
  461. status[0].Information));
  462. halt(1);
  463. }
  464. ns_log(("GspJoin: group %s mastered by %d curset %x\n",
  465. gd->g_name, mid, info.mset));
  466. ns_log(("GspJoin: Mseq %d Curview %d Gsz %d mset %x\n",
  467. info.mseq, info.viewnum, info.sz, info.mset));
  468. // init some state
  469. gd->g_curview = info.viewnum;
  470. gd->g_startview = info.viewnum;
  471. gd->g_mset = info.mset;
  472. gd->g_recv.r_mseq = info.mseq;
  473. gd->g_recv.r_bnum = 1; // set starting point
  474. gd->g_send.s_lseq = info.mseq;
  475. gd->g_sz = info.sz;
  476. GsLockExit(gd->g_lock);
  477. sz = sizeof(table);
  478. for (i = 0; i < GS_MAX_GROUP_SZ; i++) {
  479. status[i].Information = 0;
  480. io[i] = (PVOID) &table[i];
  481. table[i] = TRUE;
  482. }
  483. tag.mid = gd->g_nid;
  484. err = GspSendRequest(gd, ctx, event, GS_MSG_TYPE_JOIN, mid,
  485. tag.tag,
  486. (PVOID)&wsz, sizeof(wsz),
  487. io, sizeof(table[0]),
  488. status,
  489. GS_FLAGS_DELIVERED | GS_FLAGS_CONTINUED | GS_FLAGS_LAST,
  490. &info);
  491. if (err != ERROR_SUCCESS) {
  492. err_log(("Join failed %d\n", err));
  493. halt(1);
  494. }
  495. {
  496. int i;
  497. for (i = 0; i < GS_MAX_GROUP_SZ; i++) {
  498. if (table[i] != TRUE) {
  499. err_log(("GsJoin: Failed was rejected by member %d\n", i));
  500. halt(1);
  501. }
  502. }
  503. }
  504. if (context == NULL) {
  505. flags = GS_FLAGS_DELIVERED | GS_FLAGS_CLOSE | GS_FLAGS_LAST;
  506. } else {
  507. flags = GS_FLAGS_DELIVERED | GS_FLAGS_CONTINUED | GS_FLAGS_LAST;
  508. }
  509. // add ourself to membership set
  510. info.sz++;
  511. info.mset |= (1 << gd->g_nid);
  512. sz = 0;
  513. tag.mid = gd->g_nid;
  514. err = GspSendRequest(gd, ctx, event, GS_MSG_TYPE_UP, mid,
  515. tag.tag,
  516. (PVOID) &wsz, sizeof(wsz), NULL, 0, status, flags, &info);
  517. // advance our startview
  518. gd->g_startview++;
  519. gd->g_state = GS_GROUP_STATE_FORM;
  520. if (context != NULL) {
  521. *context = (HANDLE) ctx;
  522. } else {
  523. GspCloseContext(gd, ctx);
  524. }
  525. return 0;
  526. }
  527. return 0;
  528. }
  529. void
  530. NsJoin()
  531. {
  532. HANDLE ctx;
  533. gs_ns_info_t table[GS_MAX_GROUPS];
  534. UINT32 i, sz;
  535. PVOID io[GS_MAX_GROUP_SZ];
  536. IO_STATUS_BLOCK status[GS_MAX_GROUP_SZ];
  537. NTSTATUS err;
  538. gs_event_t event;
  539. union {
  540. int cmd;
  541. gs_tag_t tag;
  542. }tag;
  543. GsEventInit(event);
  544. GspJoin(ns_gd, event, io, status, 1, &ctx);
  545. if (ctx == NULL) {
  546. GsEventFree(event);
  547. return;
  548. }
  549. for (i = 0; i < GS_MAX_GROUP_SZ; i++) {
  550. status[i].Information = 0;
  551. io[i] = (PVOID)table;
  552. }
  553. tag.cmd = NS_TABLE_READ;
  554. err = GsSendContinuedRequest(ctx, event,
  555. tag.tag, NULL, 0,
  556. io, sizeof(table),
  557. status,
  558. TRUE);
  559. if (err != ERROR_SUCCESS) {
  560. err_log(("Table read failed %x\n", err));
  561. halt(1);
  562. }
  563. sz = 0;
  564. for (i = 0; i < GS_MAX_GROUP_SZ; i++) {
  565. if (status[i].Information != 0) {
  566. sz = ((UINT32)status[i].Information) / sizeof(table[0]);
  567. break;
  568. }
  569. }
  570. assert(i != GS_MAX_GROUP_SZ);
  571. ns_log(("NsJoin: Got table %x from master %d sz %d\n", table, i,
  572. status[i].Information));
  573. for (i = 0; i < sz; i++) {
  574. gs_group_t *gd;
  575. ns_log(("NsJoin: Table%d: %s owner %d\n",
  576. table[i].id,
  577. table[i].name, table[i].owner));
  578. gd = GspLookupGroupByName(table[i].name, strlen(table[i].name));
  579. if (gd == NULL) {
  580. gd = GspAllocateGroup(strsave(table[i].name), strlen(table[i].name));
  581. if (gd == NULL) {
  582. err_log(("unable to alloc group %s, exiting..\n",
  583. table[i].name));
  584. halt(1);
  585. }
  586. GspSetMaster(gd, table[i].owner);
  587. } else {
  588. err_log(("found group %s already, exiting..\n", table[i].name));
  589. halt(1);
  590. }
  591. }
  592. GsEventFree(event);
  593. }