distNameLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:46k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* distNameLib.c - distributed name database library (VxFusion option) */
  2. /* Copyright 1999-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01r,05dec01,jws  no ARM cross endian FP support (SPR 70116 final)
  7. 01q,06nov01,jws  move tmp declaration
  8. 01p,22oct01,jws  eliminate compiler warnings (SPR 71117)
  9.                  man pages update (SPR 71239)
  10. 01o,15oct01,jws  merge ARM FP format handling back from AE (SPR 70116 prelim)
  11. 01n,24may99,drm  added vxfusion prefix to VxFusion related includes
  12. 01m,23feb99,wlf  doc edits
  13. 01l,18feb99,wlf  doc cleanup
  14. 01k,13feb99,drm  Added two routines for flipping bytes of UINT64/double
  15. 01j,12feb99,drm  Fixed a bug in DistNameMatchOne to fix SPR #25002
  16. 01i,28oct98,drm  documentation modifications
  17. 01h,11sep98,drm  added #include to pick up distPanic()
  18. 01g,13may98,ur   some cleanup, when distNameInit() fails
  19. 01f,08may98,ur   removed 8 bit node id restriction
  20. 01e,15apr98,ur   distNameRemove() returns node to free list
  21. 01d,15apr98,ur   name database update returns OK, even if broadcast failed
  22. 01c,30mar98,ur   added some more errnos;
  23.  changed VALUE_TOO_LONG to ILLEGAL_LENGTH.
  24. 01b,27jun97,ur   tested - ok.
  25. 01a,06jun97,ur   written.
  26. */
  27. /*
  28. DESCRIPTION
  29. This library contains the distributed objects distributed name database and
  30. routines for manipulating it.  Symbolic names are bound to values, such as
  31. message queue identifiers or simple integers. Entries can be found by name
  32. or by value and type.  The distributed name database is replicated
  33. throughout the system, with a copy sitting on each node.
  34. The distributed name database library is initialized by calling
  35. distInit() in distLib.
  36. AVAILABILITY
  37. This module is distributed as a component of the unbundled distributed
  38. message queues option, VxFusion.
  39. INCLUDE FILES: distNameLib.h
  40. SEE ALSO: distLib, distNameShow
  41. */
  42. #include "vxWorks.h"
  43. #if defined (DIST_NAME_REPORT) || defined (DIST_DIAGNOSTIC)
  44. #include "stdio.h"
  45. #endif
  46. #include "stdlib.h"
  47. #include "string.h"
  48. #include "semLib.h"
  49. #include "private/semLibP.h"
  50. #include "sllLib.h"
  51. #include "hashLib.h"
  52. #include "msgQLib.h"
  53. #include "errnoLib.h"
  54. #include "netinet/in.h"
  55. #include "vxfusion/msgQDistLib.h"
  56. #include "vxfusion/distNameLib.h"
  57. #include "vxfusion/distIfLib.h"
  58. #include "vxfusion/distStatLib.h"
  59. #include "vxfusion/private/distLibP.h"
  60. #include "vxfusion/private/distObjLibP.h"
  61. #include "vxfusion/private/msgQDistLibP.h"
  62. #include "vxfusion/private/distTBufLibP.h"
  63. #include "vxfusion/private/distNetLibP.h"
  64. #include "vxfusion/private/distPktLibP.h"
  65. #include "vxfusion/private/distNameLibP.h"
  66. /* defines */
  67. #define UNUSED_ARG(x)  if(sizeof(x)) {} /* to suppress compiler warnings */
  68. #define XFLOAT 0     /* no ARM cross-endian support for VxWorks 5.x */
  69. #define KEY_ARG 65537 /* seed for hash function */
  70. #define KEY_CMP_ARG 0 /* not used */
  71. /* locals */
  72. LOCAL HASH_ID distNameDbId;
  73. LOCAL SEMAPHORE distNameDbLock;
  74. LOCAL SEMAPHORE distNameDbUpdate;
  75. LOCAL SL_LIST distNameFreeList;
  76. LOCAL BOOL distNameLibInstalled = FALSE;
  77. /* local prototypes */
  78. LOCAL STATUS distNameLclAdd (char *name, int nameLen, void *value,
  79. int valueLen, DIST_NAME_TYPE type);
  80. LOCAL DIST_NAME_DB_NODE * distNameLclAddRaw (char *name, int nameLen,
  81.         void *value, int valueLen,
  82.      DIST_NAME_TYPE type);
  83. LOCAL STATUS distNameRmtAdd (DIST_NODE_ID nodeId, char *name,
  84. int nameLen, void *value,
  85. int valueLen,
  86. DIST_NAME_TYPE type);
  87. LOCAL STATUS distNameLclRemove (char *name, int nameLen);
  88. LOCAL int distNameHFunc (int elements,
  89.                                        DIST_NAME_DB_NODE *pHNode,
  90.        int seed);
  91. LOCAL BOOL distNameHCmp (DIST_NAME_DB_NODE *pMatchHNode,
  92.       DIST_NAME_DB_NODE *pHNode,
  93.       int keyCmpArg);
  94. LOCAL DIST_STATUS distNameInput (DIST_NODE_ID nodeIdSrc,
  95.        DIST_TBUF_HDR *pTBufHdr);
  96. LOCAL BOOL distNameMatchOne (DIST_NAME_DB_NODE *pNode,
  97.   DIST_NAME_MATCH *pMatch);
  98. LOCAL BOOL distNameBurstOne (DIST_NAME_DB_NODE *pNode,
  99.   DIST_NAME_BURST *pBurst);
  100. LOCAL uint32_t * distHton64 (uint32_t* hostValue, DIST_NAME_TYPE type);
  101. LOCAL uint32_t * distNtoh64 (uint32_t* networkValue, DIST_NAME_TYPE type);
  102. /***************************************************************************
  103. *
  104. * distNameLibInit - initialize the distributed name database package (VxFusion option)
  105. *
  106. * Initialize the distributed name database package.  This routine currently
  107. * does nothing.
  108. *
  109. * AVAILABILITY
  110. * This routine is distributed as a component of the unbundled distributed
  111. * message queues option, VxFusion.
  112. *
  113. * RETURNS: N/A
  114. *
  115. * NOMANUAL
  116. */
  117. void distNameLibInit (void)
  118.     {
  119.     }
  120. /***************************************************************************
  121. *
  122. * distNameInit - initialize the distributed name database (VxFusion option)
  123. *
  124. * This routine allocates space for the distributed name database and
  125. * initializes it. The database has 2^<sizeLog2> nodes.
  126. *
  127. * NOTE: This routine is called by distInit(). If you use distInit() to
  128. * initialize a node, you need not call distNameInit().
  129. *
  130. * AVAILABILITY
  131. * This routine is distributed as a component of the unbundled distributed
  132. * message queues option, VxFusion.
  133. *
  134. * RETURNS: OK, if nodes successfully initialized.
  135. *
  136. * SEE ALSO: distLib
  137. *
  138. * NOMANUAL
  139. */
  140. STATUS distNameInit
  141.     (
  142.     int sizeLog2        /* init 2^sizeLog2 elements */
  143.     )
  144.     {
  145.     DIST_NAME_DB_NODE *   nameDb;
  146.     STATUS                status;
  147.     int                   hashTblSizeLog2;
  148.     int                   nameDbNBytes;
  149.     int                   nameDbSize;
  150.     int                   ix;
  151.     if (sizeLog2 < 1)
  152.         return (ERROR);
  153.     if (distNameLibInstalled == TRUE)
  154.         return (OK);
  155.     if (hashLibInit () == ERROR)    /* hashLibInit() failed */
  156.         return (ERROR);
  157.     semBInit (&distNameDbLock, SEM_Q_PRIORITY, SEM_EMPTY);
  158.     semBInit (&distNameDbUpdate, SEM_Q_PRIORITY, SEM_EMPTY);
  159.     hashTblSizeLog2 = sizeLog2 - 1;
  160.     distNameDbId = hashTblCreate (hashTblSizeLog2, distNameHCmp,
  161.                                   distNameHFunc, KEY_ARG);
  162.     if (distNameDbId == NULL)   /* hashTblCreate() failed */
  163.         return (ERROR);
  164.     nameDbSize = 1 << sizeLog2;
  165.     nameDbNBytes = nameDbSize * sizeof (DIST_NAME_DB_NODE);
  166.     nameDb = (DIST_NAME_DB_NODE *) malloc (nameDbNBytes);
  167.     if (nameDb == NULL)
  168.         {
  169.         distStat.memShortage++;         /* out of memory */
  170.         hashTblDelete (distNameDbId);   /* delete the hash table */
  171.         return (ERROR);                 /* init failed */
  172.         }
  173.     sllInit (&distNameFreeList);
  174.     for (ix = 0; ix < nameDbSize; ix++)
  175.         sllPutAtHead (&distNameFreeList, (SL_NODE *) &nameDb[ix]);
  176.     /* we are open for requests now */
  177.     semGive (&distNameDbLock);
  178.     /*
  179.      * Add GAP service to table of services.
  180.      */
  181.     status = distNetServAdd (DIST_PKT_TYPE_DNDB, distNameInput,
  182.                              DIST_DNDB_SERV_NAME, DIST_DNDB_SERV_NET_PRIO,
  183.                              DIST_DNDB_SERV_TASK_PRIO,
  184.                              DIST_DNDB_SERV_TASK_STACK_SZ);
  185.     if (status == ERROR)
  186.         {
  187.         free (nameDb);                 /* free database memory */
  188.         hashTblDelete (distNameDbId);  /* delete the hash table */
  189.         return (ERROR);                /* init failed */
  190.         }
  191.     distNameLibInstalled = TRUE;
  192.     return (OK);
  193.     }
  194. /***************************************************************************
  195. *
  196. * distNameAdd - add an entry to the distributed name database (VxFusion option)
  197. *
  198. * This routine adds the name of a specified object, along with its type and 
  199. * value, to the distributed objects distributed name database. All copies of 
  200. * the distributed name database within the system are updated.
  201. * The <name> parameter is an arbitrary, null-terminated string with a
  202. * maximum of 20 characters, including the null terminator.
  203. *
  204. * The value associated with <name> is located at <value> and is of length
  205. * <valueLen>, currently limited to 8 bytes.
  206. *
  207. * By convention, <type> values of less than 0x1000 are reserved by VxWorks;
  208. * all other values are user definable.  The following types are pre-defined
  209. * in distNameLib.h :
  210. *
  211. * ts
  212. * Type Name | Value | Datum
  213. * ----------|------------|------
  214. *     T_DIST_MSG_Q |  =  0 | distributed message queue 
  215. *     T_DIST_NODE | = 16 | node ID
  216. *     T_DIST_UINT8 | = 64 | 8-bit unsigned integer
  217. *     T_DIST_UINT16 | = 65 | 16-bit unsigned integer
  218. *     T_DIST_UINT32 | = 66 | 32-bit unsigned integer
  219. *     T_DIST_UINT64 | = 67 | 64-bit unsigned integer
  220. *     T_DIST_FLOAT | = 68 | float (32-bit)
  221. *     T_DIST_DOUBLE | = 69 | double (64-bit)
  222. * te
  223. *
  224. * The byte-order of pre-defined types is preserved in a
  225. * byte-order-heterogeneous network.
  226. *
  227. * The value (and type!) bound to a symbolic name can be changed by calling
  228. * distNameAdd() with a new value (and type).
  229. *
  230. * This routine returns OK, even if some nodes on the system do not
  231. * respond to the add request broadcast. A node that does not acknowledge
  232. * a transmission is assumed to have crashed. You can use the distCtl() routine
  233. * in distLib to set a routine to be called in the event that a node crashes.
  234. *
  235. * NOTE:
  236. * If you add a distributed object ID (T_DIST_MSG_Q) to the database,
  237. * another reference to the object is built. This reference is stored
  238. * in the database. After the return of distNameAdd(), <value> holds the
  239. * reference (a new object ID). Use the ID returned by
  240. * distNameAdd() each time you want to address the global object bound
  241. * to <name>. Subsequent updates of the binding in the database are
  242. * transparent. The original object ID specifies exactly the
  243. * locally created object.
  244. *
  245. * AVAILABILITY
  246. * This routine is distributed as a component of the unbundled distributed
  247. * message queues option, VxFusion.
  248. *
  249. * RETURNS: OK, or ERROR if the operation fails.
  250. *
  251. * ERRNO:
  252. * is
  253. * i S_distNameLib_NAME_TOO_LONG
  254. * The name being added to the database is too long.
  255. * i S_distNameLib_ILLEGAL_LENGTH
  256. * The argument <valueLen> is not in the range 1 to 8.
  257. * i S_distNameLib_DATABASE_FULL
  258. * The database is full.
  259. * i S_distNameLib_INCORRECT_LENGTH
  260. * The argument <valueLen> is incorrect for the pre-defined <type>.
  261. * ie
  262. *
  263. * SEE ALSO: distLib
  264. */
  265. STATUS distNameAdd
  266.     (
  267.     char *          name,       /* name to enter in database  */
  268.     void *          value,      /* ptr to value to associate with name */
  269.     int             valueLen,   /* size of value in bytes     */
  270.     DIST_NAME_TYPE  type        /* type associated with name  */
  271.     )
  272.     {
  273.     int        nameLen;
  274. #ifdef DIST_DIAGNOSTIC
  275.     STATUS    status;
  276. #endif
  277.     if ((nameLen = strlen (name)) > DIST_NAME_MAX_LENGTH)
  278.         {
  279.         errnoSet (S_distNameLib_NAME_TOO_LONG);
  280.         return (ERROR);    /* name too long */
  281.         }
  282.     if (valueLen <= 0 || valueLen > DIST_VALUE_MAX_LENGTH)
  283.         {
  284.         errnoSet (S_distNameLib_ILLEGAL_LENGTH);
  285.         return (ERROR);    /* size of value out of range */
  286.         }
  287.     switch (type)
  288.         {
  289.         case T_DIST_UINT8:
  290.             if (valueLen != 1)
  291.                 {
  292.                 errnoSet (S_distNameLib_INCORRECT_LENGTH);
  293.                 return (ERROR);
  294.                 }
  295.             break;
  296.         case T_DIST_UINT16:
  297.             if (valueLen != 2)
  298.                 {
  299.                 errnoSet (S_distNameLib_INCORRECT_LENGTH);
  300.                 return (ERROR);
  301.                 }
  302.             break;
  303.         case T_DIST_FLOAT:
  304.         case T_DIST_UINT32:
  305.         case T_DIST_NODE:
  306.             if (valueLen != 4)
  307.                 {
  308.                 errnoSet (S_distNameLib_INCORRECT_LENGTH);
  309.                 return (ERROR);
  310.                 }
  311.             break;
  312.         case T_DIST_UINT64:
  313.         case T_DIST_DOUBLE:
  314.             if (valueLen != 8)
  315.                 {
  316.                 errnoSet (S_distNameLib_INCORRECT_LENGTH);
  317.                 return (ERROR);
  318.                 }
  319.         /* case T_DIST_MSG_Q: no checking for complex object type */
  320.         }
  321.     /* Local name database update. */
  322.     if (distNameLclAdd (name, nameLen, value, valueLen, type) == ERROR)
  323.         {
  324. #ifdef DIST_DIAGNOSTIC
  325.         distLog ("distNameAdd: error updating local name databasen");
  326. #endif
  327.         errnoSet (S_distNameLib_DATABASE_FULL);
  328.         return (ERROR);
  329.         }
  330.     /* Remote name database update. */
  331. #ifdef DIST_DIAGNOSTIC
  332.     status = distNameRmtAdd (DIST_IF_BROADCAST_ADDR, name, nameLen, value,
  333.                              valueLen, type);
  334.     if (status == ERROR)
  335.         {
  336.         /* Local node has binding--one of the remote nodes may not. */
  337.         distLog ("distNameAdd: error updating remote name databasesn");
  338.         }
  339. #else
  340.     distNameRmtAdd (DIST_IF_BROADCAST_ADDR, name, nameLen, value,
  341.                     valueLen, type);
  342. #endif
  343.     return (OK);    /* return OK, always */
  344.     }
  345. /***************************************************************************
  346. *
  347. * distNameLclAdd - bind name to value in local name database (VxFusion option)
  348. *
  349. * This routine binds a name to a given value in name database. If <type>
  350. * is a distributed object preprocess and postprocess identifier.
  351. *
  352. * NOTE: Before calling distNameLclAdd(), nameLen and valueLen
  353. * must been tested to prevent overflows.
  354. *
  355. * AVAILABILITY
  356. * This routine is distributed as a component of the unbundled distributed
  357. * message queues option, VxFusion.
  358. *
  359. * RETURNS: OK, if successful.
  360. *
  361. * NOMANUAL
  362. */
  363. LOCAL STATUS distNameLclAdd
  364.     (
  365.     char *         name,     /* name to enter in database */
  366.     int            nameLen,  /* strlen (name) */
  367.     void *         value,    /* value associated with name */
  368.     int            valueLen, /* size of value in bytes */
  369.     DIST_NAME_TYPE type      /* type associated with name */
  370.     )
  371.     {
  372.     DIST_NAME_DB_NODE * pDbNode;
  373.     DIST_OBJ_NODE *     pObjNode;
  374.     void *              pVal;
  375.     MSG_Q_ID            msgQId;
  376.     /* Preprocessing */
  377.     switch (type)
  378.         {
  379.         case T_DIST_MSG_Q:
  380.             {
  381.             /*
  382.              * A little tricky, what we do here: user gives us a
  383.              * message queue id. Check if it is a distributed
  384.              * message id. If not, return ERROR.
  385.              * Create a new DIST_OBJ_NODE and copy distributed
  386.              * id to new DIST_OBJ_NODE. Return the new MSG_Q_ID
  387.              * (which is in fact another reference to the MSG_Q_ID,
  388.              * the user gave us).
  389.              */
  390.             msgQId = *((MSG_Q_ID *) value);
  391.             if (!ID_IS_DISTRIBUTED (msgQId))
  392.                 return (ERROR);    /* not a distributed message queue */
  393.             if (DIST_OBJ_VERIFY (msgQId) == ERROR)
  394.                 return (ERROR);
  395.             pObjNode = MSG_Q_ID_TO_DIST_OBJ_NODE (msgQId);
  396.             if (! IS_DIST_MSG_Q_OBJ (pObjNode))
  397.                 return (ERROR); /* legal object id, but not a message queue */
  398.             pVal = &(pObjNode->objNodeUniqId);
  399.             valueLen = sizeof (pObjNode->objNodeUniqId);
  400.             break;
  401.             }
  402.         default:
  403.             pVal = value;
  404.         }
  405.     /* Local database update (raw part). */
  406.     pDbNode = distNameLclAddRaw (name, nameLen, pVal, valueLen, type);
  407.     if (pDbNode == NULL)
  408.         return (ERROR);
  409.     /* Postprocessing */
  410.     switch (type)
  411.         {
  412.         case T_DIST_MSG_Q:
  413.             *((MSG_Q_ID *) value) = *((MSG_Q_ID *) &pDbNode->value);
  414.         }
  415.     return (OK);
  416.     }
  417. /***************************************************************************
  418. *
  419. * distNameBurst - burst out name database (VxFusion option)
  420. *
  421. * This routine is used by INCO to update the remote name database on
  422. * node <nodeId>. All entries in the database are transmitted.
  423. *
  424. * AVAILABILITY
  425. * This routine is distributed as a component of the unbundled distributed
  426. * message queues option, VxFusion.
  427. *
  428. * RETURNS: OK, if successful.
  429. *
  430. * NOMANUAL
  431. */
  432. STATUS distNameBurst
  433.     (
  434.     DIST_NODE_ID    nodeId    /* node receiving burst */
  435.     )
  436.     {
  437.     DIST_NAME_BURST    burst;
  438.     burst.burstNodeId = nodeId;
  439.     burst.burstStatus = OK;
  440.     distNameEach ((FUNCPTR) distNameBurstOne, (int) &burst);
  441.     return (burst.burstStatus);
  442.     }
  443. /***************************************************************************
  444. *
  445. * distNameBurstOne - burst out single name database entry (VxFusion option)
  446. *
  447. * This routine bursts out a single database entry to a node.
  448. *
  449. * AVAILABILITY
  450. * This routine is distributed as a component of the unbundled distributed
  451. * message queues option, VxFusion.
  452. *
  453. * RETURNS: TRUE, if burst out successful
  454. *
  455. * NOMANUAL
  456. */
  457. LOCAL BOOL distNameBurstOne
  458.     (
  459.     DIST_NAME_DB_NODE * pNode,   /* node receiving burst */
  460.     DIST_NAME_BURST *   pBurst   /* the entry to send */
  461.     )
  462.     {
  463.     char    *name = (char *) &pNode->symName;
  464.     if ((pBurst->burstStatus = distNameRmtAdd (pBurst->burstNodeId,
  465.             name, strlen (name), &pNode->value, pNode->valueLen,
  466.             pNode->type)) == ERROR)
  467.         return (FALSE);
  468.     return (TRUE);
  469.     }
  470. /***************************************************************************
  471. *
  472. * distNameRmtAdd - bind name to value in remote name databases (VxFusion option)
  473. *
  474. * This routine adds or updates a name/value pair in a remote node.
  475. *
  476. * NOTE: Before calling distNameRmtAdd(), nameLen and valueLen
  477. * must been tested to prevent overflows.
  478. *
  479. * AVAILABILITY
  480. * This routine is distributed as a component of the unbundled distributed
  481. * message queues option, VxFusion.
  482. *
  483. * RETURNS: OK, if successful.
  484. *
  485. * NOMANUAL
  486. */
  487. LOCAL STATUS distNameRmtAdd
  488.     (
  489.     DIST_NODE_ID    nodeId,     /* node to address */
  490.     char *          name,       /* name to enter in database */
  491.     int             nameLen,    /* strlen (name) */
  492.     void *          value,      /* value associated with name */
  493.     int             valueLen,   /* size of value in bytes */
  494.     DIST_NAME_TYPE  type        /* type associated with name */
  495.     )
  496.     {
  497.     DIST_NAME_TYPE_ALL    valNet;
  498.     DIST_PKT_DNDB_ADD     pktDndbAdd;
  499.     DIST_IOVEC            IOVec[3];
  500.     STATUS                status;
  501.     void *                pValNet;
  502.     DIST_OBJ_UNIQ_ID *    pObjUniqId;
  503.     DIST_OBJ_NODE *       pObjNode;
  504.     MSG_Q_ID              msgQId;
  505.     /*
  506.      * We have to copy data, since some processors allow
  507.      * memory requests to non-aligned addresses, others
  508.      * don't.
  509.      */
  510.     switch (type)
  511.         {
  512.         case T_DIST_UINT8:
  513.             {
  514.             pValNet = value;
  515.             break;
  516.             }
  517.         case T_DIST_UINT16:
  518.             {
  519.             bcopy (value, (char *) &(valNet.uint16), valueLen);
  520.             valNet.uint16 = htons (valNet.uint16);
  521.             pValNet = &(valNet.uint16);
  522.             break;
  523.             }
  524.         case T_DIST_NODE:
  525.         case T_DIST_FLOAT:
  526.         case T_DIST_UINT32:
  527.             {
  528.             bcopy (value, (char *) &(valNet.uint32), valueLen);
  529.             valNet.uint32 = htonl (valNet.uint32);
  530.             pValNet = &valNet.uint32;
  531.             break;
  532.             }
  533.         case T_DIST_UINT64:
  534.         case T_DIST_DOUBLE:
  535.             {
  536.             bcopy (value, (char *) &(valNet.uint64), valueLen);
  537.             pValNet = distHton64((uint32_t*)&(valNet.uint64),type);
  538.             break;
  539.             }
  540.         case T_DIST_MSG_Q:        /* complex objects go here */
  541.             {
  542.             /*
  543.              * A little tricky, what we do here: user gives us a
  544.              * message queue id. Check if it is a distributed
  545.              * message id. If not, return ERROR.
  546.              * Get the distributed (unique!) id instead of the
  547.              * local MSG_Q_ID (local pointer).
  548.              */
  549.             msgQId = *((MSG_Q_ID *) value);
  550.             if (!ID_IS_DISTRIBUTED (msgQId))
  551.                 return (ERROR);    /* not a distributed message queue */
  552.             if (DIST_OBJ_VERIFY (msgQId) == ERROR)
  553.                 return (ERROR);
  554.             pObjNode = MSG_Q_ID_TO_DIST_OBJ_NODE (msgQId);
  555.             if (! IS_DIST_MSG_Q_OBJ (pObjNode))
  556.                 return (ERROR); /* legal object id, but not a message queue */
  557.             bcopy ((char *) &(pObjNode->objNodeUniqId),
  558.                    (char *) &(valNet.objUniqId),
  559.                    sizeof (pObjNode->objNodeUniqId));
  560.             pObjUniqId = (DIST_OBJ_UNIQ_ID *) &(valNet.objUniqId);
  561.             pObjUniqId->objUniqReside    = htonl (pObjUniqId->objUniqReside);
  562.             pObjUniqId->objUniqId        = htonl (pObjUniqId->objUniqId);
  563.             pValNet = pObjUniqId;
  564.             valueLen = sizeof (*pObjUniqId);
  565.             break;
  566.             }
  567.         default:
  568.             pValNet = value;    /* user defined, do not know what to do */
  569.         }
  570.     /* Remote database update. */
  571.     pktDndbAdd.dndbAddHdr.pktType = DIST_PKT_TYPE_DNDB;
  572.     pktDndbAdd.dndbAddHdr.pktSubType = DIST_PKT_TYPE_DNDB_ADD;
  573.     pktDndbAdd.dndbAddType = htons (type);
  574.     pktDndbAdd.dndbAddValueLen = (UINT8) valueLen;
  575.     pktDndbAdd.dndbAddNameLen = (UINT8) nameLen;
  576.     IOVec[0].pIOBuffer = &pktDndbAdd;
  577.     IOVec[0].IOLen = DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD);
  578.     IOVec[1].pIOBuffer = pValNet;
  579.     IOVec[1].IOLen = valueLen;
  580.     IOVec[2].pIOBuffer = name;
  581.     IOVec[2].IOLen = nameLen;
  582.     status = distNetIOVSend (nodeId, &IOVec[0], 3, WAIT_FOREVER,
  583.             DIST_PKT_DNDB_PRIO);
  584.     return (status);
  585.     }
  586. /***************************************************************************
  587. *
  588. * distNameFind - find an object by name in the local database (VxFusion option)
  589. *
  590. * This routine searches the distributed name database for an object matching
  591. * a specified <name>. If the object is found, a pointer to the value and its
  592. * type are copied to the address pointed to by <pValue> and <pType>.
  593. * If the type is T_DIST_MSG_Q, the identifier returned can be used with
  594. * generic message queue handling routines in msgQLib, such as msgQSend(), 
  595. * msgQReceive(), and msgQNumMsgs().
  596. *
  597. * AVAILABILITY
  598. * This routine is distributed as a component of the unbundled distributed
  599. * message queues option, VxFusion.
  600. *
  601. * RETURNS: OK, or ERROR if the search fails.
  602. *
  603. * ERRNO:
  604. * is
  605. * i S_distNameLib_NAME_TOO_LONG
  606. * The name to be found in the database is too long.
  607. * i S_distNameLib_INVALID_WAIT_TYPE
  608. * The wait type should be either NO_WAIT or WAIT_FOREVER .
  609. * ie
  610. */
  611. STATUS distNameFind
  612.     (
  613.     char *           name,    /* name to search for            */
  614.     void **          pValue,  /* where to return ptr to value */
  615.     DIST_NAME_TYPE * pType,   /* where to return type  */
  616.     int              waitType /* NO_WAIT or WAIT_FOREVER       */
  617.     )
  618.     {
  619.     DIST_NAME_DB_NODE * pNode;
  620.     DIST_NAME_DB_NODE   matchNode;
  621.     int                 nameLen;
  622.     if ((nameLen = strlen (name)) > DIST_NAME_MAX_LENGTH)
  623.         {
  624.         errnoSet (S_distNameLib_NAME_TOO_LONG);
  625.         return (ERROR);    /* name too long */
  626.         }
  627.     if (waitType != NO_WAIT && waitType != WAIT_FOREVER)
  628.         {
  629.         errnoSet (S_distNameLib_INVALID_WAIT_TYPE);
  630.         return (ERROR); /* wait type is invalid */
  631.         }
  632.     bcopy (name, (char *) &matchNode.symName, nameLen + 1);
  633. again:
  634.     distNameLclLock();
  635.     pNode = (DIST_NAME_DB_NODE *) hashTblFind (distNameDbId,
  636.             (HASH_NODE *)&matchNode, KEY_CMP_ARG);
  637.     distNameLclUnlock();
  638.     if (!pNode)
  639.         {
  640.         if (waitType == WAIT_FOREVER)
  641.             {
  642.             /* object not found; we have to wait ... */
  643.             distNameLclBlockOnAdd();
  644.             goto again;
  645.             }
  646.         else
  647.             return (ERROR);    /* object not found */
  648.         }
  649.     
  650.     *pType = pNode->type;
  651.     *pValue = &pNode->value;
  652.     return (OK);
  653.     }
  654. /***************************************************************************
  655. *
  656. * distNameFindByValueAndType - look up the name of an object by value and type (VxFusion option)
  657. *
  658. * This routine searches the distributed name database for an object matching
  659. * a specified <value> and <type>. If the object is found, its name is 
  660. * copied to the address pointed to by <name>.
  661. *
  662. * NOTE:
  663. * Unlike the smNameFindByValue() routine, used with the shared-memory 
  664. * objects name database, this routine must know the type of the object
  665. * being searched for. Searching on the value only might not return a
  666. * unique object.
  667. * AVAILABILITY
  668. * This routine is distributed as a component of the unbundled distributed
  669. * message queues option, VxFusion.
  670. *
  671. * RETURNS: OK, or ERROR if the search fails.
  672. *
  673. * ERRNO:
  674. * is
  675. * i S_distNameLib_INVALID_WAIT_TYPE
  676. * The wait type should be either NO_WAIT or WAIT_FOREVER .
  677. * ie
  678. */
  679. STATUS distNameFindByValueAndType
  680.     (
  681.     void *           value,       /* value to search for          */
  682.     DIST_NAME_TYPE   type,        /* type of object for which to search */
  683.     char *           name,        /* where to return name */
  684.     int              waitType     /* NO_WAIT or WAIT_FOREVER      */
  685.     )
  686.     {
  687.     DIST_NAME_DB_NODE *    pNode;
  688.     DIST_NAME_MATCH        match;
  689.     if (waitType != NO_WAIT && waitType != WAIT_FOREVER)
  690.         {
  691.         errnoSet (S_distNameLib_INVALID_WAIT_TYPE);
  692.         return (ERROR); /* wait type is invalid */
  693.         }
  694.     match.pMatchValue = value;
  695.     match.matchType = type;
  696. again:
  697.     pNode = distNameEach ((FUNCPTR) distNameMatchOne, (int) &match);
  698.     if (!pNode)
  699.         {
  700.         if (waitType == WAIT_FOREVER)
  701.             {
  702.             /* object not found; we have to wait ... */
  703.             distNameLclBlockOnAdd();
  704.             goto again;
  705.             }
  706.         else
  707.             return (ERROR);    /* object not found */
  708.         }
  709.     
  710.     strcpy (name, (char *) &(pNode->symName));
  711.     return (OK);
  712.     }
  713. /***************************************************************************
  714. *
  715. * distNameMatchOne - helper for distNameFindByValueAndType() (VxFusion option)
  716. *
  717. * This routine is called by distNameFindByValueAndType() to check a database
  718. * node for a match.
  719. *
  720. * AVAILABILITY
  721. * This routine is distributed as a component of the unbundled distributed
  722. * message queues option, VxFusion.
  723. *
  724. * RETURNS: TRUE, if a match is found.
  725. *
  726. * NOMANUAL
  727. */
  728. LOCAL BOOL distNameMatchOne
  729.     (
  730.     DIST_NAME_DB_NODE * pNode,    /* database node to match */
  731.     DIST_NAME_MATCH *   pMatch    /* match data */
  732.     )
  733.     {
  734.     DIST_OBJ_NODE * pObjNodeMatch;
  735.     DIST_OBJ_NODE * pObjNodeDb;
  736.     MSG_Q_ID        msgQId;
  737.     if (pNode->type == pMatch->matchType)
  738.         {
  739.         switch (pNode->type)
  740.             {
  741.             case T_DIST_MSG_Q:
  742.                 {
  743.                 pObjNodeDb = MSG_Q_ID_TO_DIST_OBJ_NODE (pNode->value.msgQId);
  744.                 msgQId = *((MSG_Q_ID *) pMatch->pMatchValue);
  745.                 pObjNodeMatch = MSG_Q_ID_TO_DIST_OBJ_NODE (msgQId);
  746.                 /*
  747.                  * Check for equality.  For group IDs, the objUniqId 
  748.                  * referenced using objNodeId is enough.  However, for
  749.                  * normal message queues, we need to check both the objUniqId
  750.                  * (using objNodeId) and objUniqReside (using objNodeReside)
  751.                  * fields.
  752.                  */
  753.                 if (IS_DIST_MSG_Q_TYPE_GRP ( (DIST_MSG_Q_ID) 
  754.                     pObjNodeMatch->objNodeId))
  755.                     {
  756.                     if (pObjNodeDb->objNodeId == pObjNodeMatch->objNodeId)
  757.                         return (FALSE);        /* matched */
  758.                     }
  759.                 else
  760.                     {
  761.                     if ((pObjNodeDb->objNodeId ==
  762.                                  pObjNodeMatch->objNodeId)
  763.                                     && 
  764.                         (pObjNodeDb->objNodeReside ==
  765.                                  pObjNodeMatch->objNodeReside))
  766.                         {
  767.                         return (FALSE);
  768.                         }
  769.                     }
  770.                 break;
  771.                 }
  772.             default:
  773.                 {
  774.                 char    *valDb = (char *) &(pNode->value);
  775.                 char    *valMatch = (char *) pMatch->pMatchValue;
  776.                 if (! bcmp (valDb, valMatch, pNode->valueLen))
  777.                     return (FALSE);        /* matched */
  778.                 }
  779.             }
  780.         }
  781.     return (TRUE);    /* continue */
  782.     }
  783. /***************************************************************************
  784. *
  785. * distNameRemove - remove an entry from the distributed name database (VxFusion option)
  786. *
  787. * This routine removes an object, that is bound to <name>, from the
  788. * distributed name database.  All copies of the distributed name database 
  789. * get updated.
  790. *
  791. * This routine returns OK, even if some nodes on the system do not
  792. * respond to the remove request broadcast.  A node that does not acknowledge
  793. * a transmission is assumed to have crashed.
  794. * You can use the distCtl() routine
  795. * in distLib to set a routine to be called in the event that a node crashes.
  796. *
  797. * Removing the name of a distributed object ID (T_DIST_MSG_Q) does not
  798. * invalidate the object ID.
  799. *
  800. * AVAILABILITY
  801. * This routine is distributed as a component of the unbundled distributed
  802. * message queues option, VxFusion.
  803. *
  804. * RETURNS: OK, or ERROR if the operation fails.
  805. *
  806. * ERRNO:
  807. * is
  808. * i S_distNameLib_NAME_TOO_LONG
  809. * The name to be removed from the database is too long.
  810. * ie
  811. *
  812. * SEE ALSO: distLib
  813. */
  814. STATUS distNameRemove
  815.     (
  816.     char * name            /* name of object to remove */
  817.     )
  818.     {
  819.     DIST_PKT_DNDB_RM    pktDndbRm;
  820.     DIST_IOVEC          IOVec[2];
  821.     int                 nameLen;
  822. #ifdef DIST_DIAGNOSTIC
  823.     STATUS    status;
  824. #endif
  825.     if ((nameLen = strlen (name)) > DIST_NAME_MAX_LENGTH)
  826.         {
  827.         errnoSet (S_distNameLib_NAME_TOO_LONG);
  828.         return (ERROR);    /* name too long */
  829.         }
  830.     if (distNameLclRemove (name, nameLen) == ERROR)
  831.         return (ERROR); /* name not in database */
  832.     pktDndbRm.dndbRmHdr.pktType = DIST_PKT_TYPE_DNDB;
  833.     pktDndbRm.dndbRmHdr.pktSubType = DIST_PKT_TYPE_DNDB_RM;
  834.     pktDndbRm.dndbRmNameLen = (UINT8) nameLen;
  835.     IOVec[0].pIOBuffer = &pktDndbRm;
  836.     IOVec[0].IOLen = DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_RM);
  837.     IOVec[1].pIOBuffer = name;
  838.     IOVec[1].IOLen = nameLen;
  839. #ifdef DIST_DIAGNOSTIC
  840.     status = distNetIOVSend (DIST_IF_BROADCAST_ADDR, &IOVec[0], 2,
  841.                         WAIT_FOREVER, DIST_PKT_DNDB_PRIO);
  842.     if (status == ERROR)
  843.         {
  844.         /* Local node has removed binding--one of the remote nodes may not. */
  845.         distLog ("distNameRemove: error updating remote name databasesn");
  846.         }
  847. #else
  848.     distNetIOVSend (DIST_IF_BROADCAST_ADDR, &IOVec[0], 2,
  849.                     WAIT_FOREVER, DIST_PKT_DNDB_PRIO);
  850. #endif
  851.     return (OK);    /* return OK, always */
  852.     }
  853. /***************************************************************************
  854. *
  855. * distNameInput - called when a DNDB packet arrives (VxFusion option)
  856. *
  857. * This routine processes incoming DNDB packets.
  858. *
  859. * AVAILABILITY
  860. * This routine is distributed as a component of the unbundled distributed
  861. * message queues option, VxFusion.
  862. *
  863. * RETURNS: Status of packet processing.
  864. *
  865. * NOMANUAL
  866. */
  867. LOCAL DIST_STATUS distNameInput
  868.     (
  869.     DIST_NODE_ID    nodeIdSrc,    /* not currently used */
  870.     DIST_TBUF_HDR * pTBufHdr      /* points to input packet */
  871.     )
  872.     {
  873.     DIST_PKT * pPkt;
  874.     int        pktLen;
  875.     
  876.     UNUSED_ARG(nodeIdSrc);
  877.     
  878.     distStat.dndbInReceived++;
  879.     if ((pktLen = pTBufHdr->tBufHdrOverall) < sizeof (DIST_PKT))
  880.         distPanic ("distNameInput: packet too shortn");
  881.     pPkt = (DIST_PKT *) (DIST_TBUF_GET_NEXT (pTBufHdr))->pTBufData;
  882.     switch (pPkt->pktSubType)
  883.         {
  884.         case DIST_PKT_TYPE_DNDB_ADD:
  885.             {
  886.             DIST_NAME_TYPE_ALL   valNet;
  887.             DIST_PKT_DNDB_ADD    pktAdd;
  888.             DIST_NAME_DB_NODE *  pNode;
  889.             DIST_NAME_TYPE       type;
  890.             void *               pValNet;
  891.             char                 name[DIST_NAME_MAX_LENGTH + 1];
  892.             int                  valueLen;
  893.             int                  nameLen;
  894.             if (pktLen < DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD))
  895.                 distPanic ("distNameInput/ADD: packet too shortn");
  896.             distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr), 0,
  897.                     (char *)&pktAdd, DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD));
  898.             valueLen = pktAdd.dndbAddValueLen;
  899.             nameLen = pktAdd.dndbAddNameLen;
  900.             if (pktLen != DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD) +
  901.                     valueLen + nameLen)
  902.                 distPanic ("distNameInput/ADD: packet has wrong lengthn");
  903.             if (valueLen > DIST_VALUE_MAX_LENGTH)
  904.                 distPanic ("distNameInput/ADD: value too longn");
  905.             if (nameLen > DIST_NAME_MAX_LENGTH)
  906.                 distPanic ("distNameInput/ADD: name too longn");
  907.             distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr),
  908.                     (DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD) + valueLen),
  909.                     (char *) &name, nameLen);
  910.             switch ((type = ntohs (pktAdd.dndbAddType)))
  911.                 {
  912.                 case T_DIST_UINT16:
  913.                     {
  914.                     distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr),
  915.                             DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD),
  916.                             (char *) &(valNet.uint16), valueLen);
  917.                     valNet.uint16 = ntohs (valNet.uint16);
  918.                     pValNet = &(valNet.uint16);
  919.                     break;
  920.                     }
  921.                 case T_DIST_FLOAT:
  922.                 case T_DIST_UINT32:
  923.                 case T_DIST_NODE:
  924.                     {
  925.                     distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr),
  926.                             DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD),
  927.                             (char *) &(valNet.uint32), valueLen);
  928.                     valNet.uint32 = ntohl (valNet.uint32);
  929.                     pValNet = &(valNet.uint32);
  930.                     break;
  931.                     }
  932.                 case T_DIST_UINT64:
  933.                 case T_DIST_DOUBLE:
  934.                     {
  935.                     distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr),
  936.                             DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD),
  937.                             (char *) &(valNet.uint64), valueLen);
  938.                     pValNet = distNtoh64((uint32_t *)&(valNet.uint64),type);
  939.                     break;
  940.                     }
  941.                 case T_DIST_MSG_Q:    /* complex objects go here */
  942.                     {
  943.                     DIST_OBJ_UNIQ_ID    *pObjUniqId;
  944.                     distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr),
  945.                             DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD),
  946.                             (char *) &(valNet.objUniqId), valueLen);
  947.                     pObjUniqId = (DIST_OBJ_UNIQ_ID *) &(valNet.objUniqId);
  948.                     pObjUniqId->objUniqReside =
  949.                             ntohl (pObjUniqId->objUniqReside);
  950.                     pObjUniqId->objUniqId =
  951.                             ntohl (pObjUniqId->objUniqId);
  952.                     pValNet = pObjUniqId;
  953.                     break;
  954.                     }
  955.                 default:    /* T_DIST_UINT8 and user defined */
  956.                     {
  957.                     distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr),
  958.                             DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_ADD),
  959.                             (char *) &(valNet.field), valueLen);
  960.                     pValNet = &valNet.field;
  961.                     }
  962.                 }
  963.             pNode = distNameLclAddRaw ((char *) &name, nameLen, pValNet,
  964.                     valueLen, type);
  965.             if (! pNode)
  966.                 distPanic ("distNameInput/ADD: database add failedn");
  967.             return (DIST_NAME_STATUS_OK);
  968.             }
  969.         case DIST_PKT_TYPE_DNDB_RM:
  970.             {
  971.             DIST_PKT_DNDB_RM    pktRm;
  972.             char                name[DIST_NAME_MAX_LENGTH + 1];
  973.             int                 nameLen;
  974.             if (pktLen < DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_RM))
  975.                 distPanic ("distNameInput/RM: packet too shortn");
  976.             distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr), 0,
  977.                     (char *) &pktRm, DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_RM));
  978.             nameLen = pktRm.dndbRmNameLen;
  979.             if (pktLen != DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_RM) + nameLen)
  980.                 distPanic ("distNameInput/RM: packet has wrong lengthn");
  981.             if (nameLen > DIST_NAME_MAX_LENGTH)
  982.                 distPanic ("distNameInput/RM: name too longn");
  983.             distTBufCopy (DIST_TBUF_GET_NEXT (pTBufHdr),
  984.                     DIST_PKT_HDR_SIZEOF (DIST_PKT_DNDB_RM),
  985.                     (char *) &name, nameLen);
  986.             
  987.             if (distNameLclRemove (name, nameLen) == ERROR)
  988.                 distPanic ("distNameInput/RM: not in databasen");
  989.             return (DIST_NAME_STATUS_OK);
  990.             }
  991.         default:
  992. #ifdef DIST_DIAGNOSTIC
  993.             distLog ("distNameInput: unknown subtype %dn",
  994.                     pPkt->pktSubType);
  995. #endif
  996.             return (DIST_NAME_STATUS_PROTOCOL_ERROR);
  997.         }
  998.     }
  999. /***************************************************************************
  1000. *
  1001. * distNameLclAddRaw - bind name to raw value in local name database (VxFusion option)
  1002. *
  1003. * Internally used function to bind name in local database.
  1004. *
  1005. * NOTE: Before calling distNameLclAddRaw(), nameLen and valueLen
  1006. * must been tested to prevent overflows.
  1007. *
  1008. * AVAILABILITY
  1009. * This routine is distributed as a component of the unbundled distributed
  1010. * message queues option, VxFusion.
  1011. *
  1012. * RETURNS: Pointer to added node, or NULL.
  1013. *
  1014. * NOMANUAL
  1015. */
  1016. LOCAL DIST_NAME_DB_NODE * distNameLclAddRaw
  1017.     (
  1018.     char *          name,       /* name to enter in database */
  1019.     int             nameLen,    /* length of name in bytes */
  1020.     void *          value,      /* value associated with name */
  1021.     int             valueLen,   /* size of value in bytes */
  1022.     DIST_NAME_TYPE  type        /* type associated with name */
  1023.     )
  1024.     {
  1025.     DIST_NAME_DB_NODE * pDbNode;
  1026.     DIST_NAME_DB_NODE * pDbNodeOld;
  1027.     DIST_OBJ_NODE *     pObjNode;
  1028.     char *              nameDest;
  1029.     char *              valDest;
  1030. #ifdef DIST_NAME_REPORT
  1031.     printf ("distNameLclAddRaw: type %d, value: ", type);
  1032.     distDump (value, valueLen);
  1033. #endif
  1034.     /*  Get a free database node. */
  1035.     if (! (pDbNode = (DIST_NAME_DB_NODE *) sllGet (&distNameFreeList)))
  1036.         return (NULL);  /* database is full */
  1037.     nameDest = (char *) &pDbNode->symName;
  1038.     bcopy (name, nameDest, nameLen);
  1039.     *(nameDest + nameLen) = 0;
  1040.     distNameLclLock();
  1041.     /* Try to find symbolic name in database. */
  1042.     pDbNodeOld = (DIST_NAME_DB_NODE *) hashTblFind (distNameDbId,
  1043.             (HASH_NODE *) pDbNode, KEY_CMP_ARG);
  1044.     if (pDbNodeOld)
  1045.         {
  1046.         /* Symbolic name is alreay in database. Update the node. */
  1047.         sllPutAtHead (&distNameFreeList, (SL_NODE *) pDbNode);
  1048.         pDbNode = pDbNodeOld;
  1049.         if (type == T_DIST_MSG_Q)
  1050.             {
  1051.             /* New object is a distributed message queue. */
  1052.             MSG_Q_ID        msgQId;
  1053.             if (pDbNode->type == T_DIST_MSG_Q)
  1054.                 {
  1055.                 /* Old object is also a distributed message queue. */
  1056.                 msgQId = *((MSG_Q_ID *) &pDbNode->value);
  1057.                 pObjNode = MSG_Q_ID_TO_DIST_OBJ_NODE (msgQId);
  1058.                 }
  1059.             else
  1060.                 {
  1061.                 /* Old object was *NOT* a distributed message queue. */
  1062.                 pObjNode = distObjNodeGet();
  1063.                 pObjNode->objNodeType = DIST_OBJ_TYPE_MSG_Q;
  1064.                 pDbNode->value.msgQId = DIST_OBJ_NODE_TO_MSG_Q_ID (pObjNode);
  1065.                 }
  1066.             valDest = (char *) &(pObjNode->objNodeUniqId);
  1067.             }
  1068.         else
  1069.             valDest = (char *) &pDbNode->value;
  1070.         }
  1071.     else
  1072.         {
  1073.         /* Symbolic name is *NOT* in the database. */
  1074.         if (type == T_DIST_MSG_Q)
  1075.             {
  1076.             pObjNode = distObjNodeGet();
  1077.             pObjNode->objNodeType = DIST_OBJ_TYPE_MSG_Q;
  1078.             pDbNode->value.msgQId = DIST_OBJ_NODE_TO_MSG_Q_ID (pObjNode);
  1079.             valDest = (char *) &(pObjNode->objNodeUniqId);
  1080.             }
  1081.         else
  1082.             valDest = (char *) &pDbNode->value;
  1083.         }
  1084.     pDbNode->type = type;
  1085.     pDbNode->valueLen = valueLen;
  1086.     bcopy (value, valDest, valueLen);
  1087.     if (!pDbNodeOld)
  1088.         hashTblPut (distNameDbId, (HASH_NODE *) pDbNode);
  1089.     distNameLclUnlock();
  1090.     /* signal a database update to waiting tasks */
  1091.     distNameLclSigAdd();
  1092.     return (pDbNode);
  1093.     }
  1094. /***************************************************************************
  1095. *
  1096. * distNameLclRemove - remove an object from the distributed database (VxFusion option)
  1097. *
  1098. * This routines removes a name from the local name database.
  1099. *
  1100. * AVAILABILITY
  1101. * This routine is distributed as a component of the unbundled distributed
  1102. * message queues option, VxFusion.
  1103. *
  1104. * RETURNS: OK, or ERROR if name could not be removed.
  1105. *
  1106. * NOMANUAL
  1107. */
  1108. LOCAL STATUS distNameLclRemove
  1109.     (
  1110.     char *  name,            /* name of object to remove */
  1111.     int     nameLen          /* length of name without EOS */
  1112.     )
  1113.     {
  1114.     DIST_NAME_DB_NODE *  pNode;
  1115.     DIST_NAME_DB_NODE    matchNode;
  1116.     bcopy (name, (char *) &matchNode.symName, nameLen);
  1117.     *(((char *) &matchNode.symName) + nameLen) = '';
  1118.     distNameLclLock();
  1119.     pNode = (DIST_NAME_DB_NODE *) hashTblFind (distNameDbId,
  1120.             (HASH_NODE *) &matchNode, KEY_CMP_ARG);
  1121.     if (!pNode || hashTblRemove(distNameDbId, (HASH_NODE *) pNode) == ERROR)
  1122.         {
  1123.         distNameLclUnlock();
  1124.         return (ERROR);
  1125.         }
  1126.     sllPutAtHead (&distNameFreeList, (SL_NODE *) pNode); /* return node */
  1127.     distNameLclUnlock();
  1128.     return (OK);
  1129.     }
  1130. /***************************************************************************
  1131. *
  1132. * distNameHCmp - compare keys based on strings (VxFusion option)
  1133. *
  1134. * This is the hash compare function for names in the database.
  1135. *
  1136. * AVAILABILITY
  1137. * This routine is distributed as a component of the unbundled distributed
  1138. * message queues option, VxFusion.
  1139. *
  1140. * RETURNS: TRUE, if the names of the DB nodes are the same.
  1141. *
  1142. * NOMANUAL
  1143. */
  1144. LOCAL BOOL distNameHCmp
  1145.     (
  1146.     DIST_NAME_DB_NODE * pMatchHNode,   /* first node */
  1147.     DIST_NAME_DB_NODE * pHNode,        /* second node */
  1148.     int                 keyCmpArg      /* not used */
  1149.     )
  1150.     {
  1151.     
  1152.     UNUSED_ARG(keyCmpArg);
  1153.     if (strcmp ((char *)&pMatchHNode->symName, (char *)&pHNode->symName) == 0)
  1154.         return (TRUE);
  1155.     else
  1156.         return (FALSE);
  1157.     }
  1158. /***************************************************************************
  1159. *
  1160. * distNameHFunc - hashing function for strings (VxFusion option)
  1161. *
  1162. * This is the hashing function for database object names.
  1163. *
  1164. * AVAILABILITY
  1165. * This routine is distributed as a component of the unbundled distributed
  1166. * message queues option, VxFusion.
  1167. *
  1168. * RETURNS: A hash index.
  1169. *
  1170. * NOMANUAL
  1171. */
  1172. LOCAL int distNameHFunc
  1173.     (
  1174.     int                 elements,   /* size of hash table */
  1175.     DIST_NAME_DB_NODE * pHNode,     /* node whose name to hash */
  1176.     int                 seed        /* hash seed */
  1177.     )
  1178.     {
  1179.     char *tkey;
  1180.     int  hash = 0;
  1181.     /* Compute string signature (sparse 32-bit hash value) */
  1182.     for (tkey = (char *) &pHNode->symName; *tkey != ''; tkey++)
  1183.         hash = hash * seed + (unsigned int) *tkey;
  1184.     return (hash & (elements - 1));    /* mask hash to (0, elements - 1) */
  1185.     }
  1186. /***************************************************************************
  1187. *
  1188. * distNameEach - each functionality on name database (VxFusion option)
  1189. *
  1190. * Successively visits every node in the database and invokes <routine>,
  1191. * passing it argument <routineArg>.
  1192. *
  1193. * NOTE: Takes <distNameDbLock>.
  1194. *
  1195. * AVAILABILITY
  1196. * This routine is distributed as a component of the unbundled distributed
  1197. * message queues option, VxFusion.
  1198. *
  1199. * RETURNS: Pointer to last node visited.
  1200. *
  1201. * NOMANUAL
  1202. */
  1203. DIST_NAME_DB_NODE * distNameEach
  1204.     (
  1205.     FUNCPTR    routine,         /* routine to invoke */
  1206.     int        routineArg       /* argument for routine */
  1207.     )
  1208.     {
  1209.     DIST_NAME_DB_NODE * lastNode;
  1210.     distNameLclLock();
  1211.     lastNode = (DIST_NAME_DB_NODE *) hashTblEach (distNameDbId, routine,
  1212.                                                   routineArg);
  1213.     distNameLclUnlock();
  1214.     return (lastNode);
  1215.     }
  1216. /***************************************************************************
  1217. *
  1218. * distHton64 - convert a 64 bit value from host to network byte order (VxFusion option)
  1219. *
  1220. * This routine converts T_DIST_UINT64 and T_DIST_DOUBLE
  1221. * values from host to network
  1222. * byte order.  The value is converted in place.
  1223. *
  1224. * AVAILABILITY
  1225. * This routine is distributed as a component of the unbundled distributed
  1226. * message queues option, VxFusion.
  1227. *
  1228. * RETURNS: <hostValue>
  1229. *
  1230. * NOMANUAL
  1231. */
  1232. LOCAL uint32_t * distHton64
  1233.     (
  1234.     uint32_t *     hostValue,   /* ptr to value to convert */
  1235.     DIST_NAME_TYPE type         /* T_DIST_UINT64 or T_DIST_DOUBLE */
  1236.     )
  1237.     {
  1238. #if _BYTE_ORDER==_LITTLE_ENDIAN
  1239.     uint32_t tmp;
  1240. #endif
  1241. #if !XFLOAT
  1242.     UNUSED_ARG(type);
  1243. #endif
  1244. #ifndef _BYTE_ORDER
  1245. #   error "no byte order specified !!"
  1246. #endif
  1247. #if _BYTE_ORDER==_LITTLE_ENDIAN
  1248. # if XFLOAT     /* ARM little-endian with double cross */
  1249.     if (type == T_DIST_DOUBLE)
  1250.         {
  1251.         hostValue[0] = htonl(hostValue[0]);
  1252.         hostValue[1] = htonl(hostValue[1]);
  1253.         }
  1254.     else
  1255.         {
  1256.         tmp = hostValue[0];
  1257.         hostValue[0] = htonl (hostValue[1]);
  1258.         hostValue[1] = htonl (tmp);
  1259.         }
  1260. # else           /* non-ARM little-endian */
  1261.     tmp = hostValue[0];
  1262.     hostValue[0] = htonl (hostValue[1]);
  1263.     hostValue[1] = htonl (tmp);
  1264. # endif /* XFLOAT */
  1265. #endif /* _BYTE_ORDER test */
  1266.     return hostValue;
  1267.     }
  1268. /***************************************************************************
  1269. *
  1270. * distNtoh64 - convert a 64 bit value from network to host byte order (VxFusion option)
  1271. *
  1272. * This routine converts T_DIST_UINT64 and T_DIST_DOUBLE values from
  1273. * network to host byte order.  The value is converted in place.
  1274. *
  1275. * AVAILABILITY
  1276. * This routine is distributed as a component of the unbundled distributed
  1277. * message queues option, VxFusion.
  1278. *
  1279. * RETURNS: <networkValue>
  1280. *
  1281. * NOMANUAL
  1282. */
  1283. LOCAL uint32_t * distNtoh64
  1284.     (
  1285.     uint32_t *     networkValue,   /* ptr to value to convert */
  1286.     DIST_NAME_TYPE type            /* T_DIST_UINT64 or T_DIST_DOUBLE */
  1287.     )
  1288.     {
  1289. #if _BYTE_ORDER==_LITTLE_ENDIAN
  1290.     uint32_t tmp;
  1291. #endif
  1292. #if !XFLOAT
  1293.     UNUSED_ARG(type);
  1294. #endif
  1295. #ifndef _BYTE_ORDER
  1296. #   error "no byte order specified !!"
  1297. #endif
  1298. #if _BYTE_ORDER==_LITTLE_ENDIAN
  1299.     
  1300. # if XFLOAT
  1301.     if (type == T_DIST_DOUBLE)
  1302.         {
  1303.         networkValue[0] = ntohl (networkValue[0]);
  1304.         networkValue[1] = ntohl (networkValue[1]);
  1305.         }
  1306.     else
  1307.         {
  1308.         tmp=networkValue[0];
  1309.         networkValue[0] = ntohl (networkValue[1]);
  1310.         networkValue[1] = ntohl (tmp);
  1311.         }
  1312. # else
  1313.     tmp=networkValue[0];
  1314.     networkValue[0] = ntohl (networkValue[1]);
  1315.     networkValue[1] = ntohl (tmp);
  1316. # endif /* XFLOAT */
  1317. #endif /* _BYTE_ORDER test */
  1318.     return networkValue;
  1319.     }