b84cbd5c81edcb6b5c55c347d25afe0122d6b91b
1 /*
2 * Copyright (c) 2012-2013, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*!
33 * @file NameServer.c
34 *
35 * @brief NameServer Manager
36 *
37 */
40 /* Standard headers */
41 #include <ti/ipc/Std.h>
43 /* Qnx specific header files */
44 #include <pthread.h>
46 /* Socket Headers */
47 #include <sys/queue.h>
48 #include <sys/select.h>
49 #include <sys/time.h>
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <errno.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <assert.h>
58 #include <fcntl.h>
60 /* Module level headers */
61 #include <ti/ipc/NameServer.h>
62 #include <ti/ipc/MultiProc.h>
63 #include <_MultiProc.h>
64 #include <ti/ipc/MessageQCopy.h>
66 /* Internal stuff: */
67 #include <_MessageQCopy.h>
68 #include <_NameServer.h>
69 #include <_NameServerRemoteRpmsg.h>
70 #include <_IpcLog.h>
72 /* TI Ipc utils: */
73 #include <TiIpcFxns.h>
75 #include "ti/ipc/ti_ipc.h"
77 #define MESSAGEQ_RPMSG_PORT 61
78 #define NAME_SERVER_RPMSG_ADDR 0
79 #define RPMSG_RESERVED_ADDRESSES (1024)
81 #define INVALIDSOCKET (-1)
83 #if defined (__cplusplus)
84 extern "C" {
85 #endif
88 /* =============================================================================
89 * Structures & Enums
90 * =============================================================================
91 */
93 /* Structure of entry in Name/Value table */
94 typedef struct NameServer_TableEntry_tag {
95 CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
96 /* List element */
97 UInt32 hash;
98 /* Hash value */
99 String name;
100 /* Name portion of the name/value pair. */
101 UInt len;
102 /* Length of the value field. */
103 Ptr value;
104 /* Value portion of the name/value entry. */
105 Bool collide;
106 /* Does the hash collide? */
107 struct NameServer_TableEntry_tag * next;
108 /* Pointer to the next entry, used incase of collision only */
109 } NameServer_TableEntry;
111 /* Structure defining object for the NameServer */
112 struct NameServer_Object {
113 CIRCLEQ_ENTRY(NameServer_Object) elem;
114 CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
115 String name; /* name of the instance */
116 NameServer_Params params; /* the parameter structure */
117 UInt32 count; /* count of entries */
118 pthread_mutex_t gate; /* crit sect gate */
119 } NameServer_Object;
121 /* structure for NameServer module state */
122 typedef struct NameServer_ModuleObject {
123 CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
124 Int32 refCount;
125 MessageQCopy_Handle mq;
126 /* MessageQCopy instance to receive from remote proc nameserver ports: */
127 UInt32 recvAddr;
128 /* Local endpoint for receiving from remote proc nameserver ports: */
129 pthread_t listener;
130 /* Listener thread for NameServer replies and requests. */
131 int waitFdW;
132 int waitFdR;
133 /* Pipe to post to NameServer_get. */
134 NameServerMsg nsMsg;
135 /* NameServer Message cache. */
136 NameServer_Params defInstParams;
137 /* Default instance paramters */
138 pthread_mutex_t modGate;
139 } NameServer_ModuleObject;
141 #define CIRCLEQ_destruct(head) { \
142 (head)->cqh_first = NULL; \
143 (head)->cqh_last = NULL; \
144 }
146 #define CIRCLEQ_elemClear(elem) { \
147 (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
148 }
150 #define CIRCLEQ_traverse(x, y, tag) \
151 for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
153 /* =============================================================================
154 * Globals
155 * =============================================================================
156 */
157 /*
158 * NameServer_state
159 *
160 * Make the module gate "recursive" since NameServer_getHandle() needs to
161 * use it and NameServer_create() needs to hold it around its call to
162 * NameServer_getHandle(). Also, use the static initializer instead of a
163 * run-time init call, so we can use this gate immediately in _setup().
164 */
165 static NameServer_ModuleObject NameServer_state = {
166 .defInstParams.maxRuntimeEntries = 0u,
167 .defInstParams.tableHeap = NULL,
168 .defInstParams.checkExisting = TRUE,
169 .defInstParams.maxValueLen = 0u,
170 .defInstParams.maxNameLen = 16u,
171 // .modGate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
172 .modGate = PTHREAD_RMUTEX_INITIALIZER,
173 .refCount = 0
174 };
176 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
178 static const UInt32 stringCrcTab[256u] = {
179 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
180 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
181 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
182 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
183 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
184 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
185 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
186 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
187 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
188 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
189 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
190 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
191 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
192 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
193 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
194 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
195 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
196 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
197 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
198 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
199 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
200 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
201 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
202 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
203 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
204 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
205 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
206 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
207 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
208 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
209 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
210 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
211 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
212 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
213 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
214 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
215 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
216 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
217 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
218 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
219 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
220 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
221 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
222 };
224 static UInt32 stringHash(String s)
225 {
226 UInt32 hash = strlen(s);
227 UInt32 i;
229 for (i = 0; i < strlen(s); i++) {
230 hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
231 }
233 return (hash);
234 }
236 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
237 {
238 NameServer_Handle handle;
239 Int status = NameServer_E_FAIL;
240 char buf = 'n';
241 int numBytes;
242 int waitFd = NameServer_module->waitFdW;
244 if (msg->request == NAMESERVER_REQUEST) {
245 LOG2("NameServer Request: instanceName: %s, name: %s\n",
246 (String)msg->instanceName, (String)msg->name)
248 /*
249 * Message is a request. Lookup name in NameServer table.
250 * Send a response message back to source processor.
251 */
252 handle = NameServer_getHandle((String)msg->instanceName);
254 if (handle != NULL) {
255 /* Search for the NameServer entry */
256 LOG0("Calling NameServer_getLocalUInt32...\n")
257 status = NameServer_getLocalUInt32(handle,
258 (String)msg->name, &msg->value);
259 }
261 LOG2("NameServer Response: instanceName: %s, name: %s,",
262 (String)msg->instanceName, (String)msg->name)
263 /* set the request status */
264 if (status < 0) {
265 LOG1(" Value not found, status: %d\n", status)
266 msg->requestStatus = 0;
267 }
268 else {
269 msg->requestStatus = 1;
270 LOG1(" Value: 0x%x\n", msg->value)
271 }
273 /* specify message as a response */
274 msg->request = NAMESERVER_RESPONSE;
275 msg->reserved = NAMESERVER_MSG_TOKEN;
277 /* send response message to remote processor */
278 status = MessageQCopy_send(procId, MultiProc_self(),
279 MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
280 sizeof(NameServerMsg), TRUE);
281 if (status < 0) {
282 LOG0("NameServer: MessageQCopy_send failed\n")
283 }
284 }
285 else {
286 LOG2("NameServer Reply: instanceName: %s, name: %s",
287 (String)msg->instanceName, (String)msg->name)
288 LOG1(", value: 0x%x\n", msg->value)
290 /* Save the response message. */
291 memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
293 /* Post the eventfd upon which NameServer_get() is waiting */
294 numBytes = write(waitFd, &buf, sizeof(buf));
295 }
296 }
298 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
299 void * priv, UInt32 src, UInt16 srcProc)
300 {
301 NameServerMsg msg;
303 LOG0("listener_cb: Entered Listener thread.\n")
305 LOG1("NameServer: Listener got NameServer message "
306 "from MessageQCopy: 0x%x!\n", handle);
307 /* Get NameServer message and process: */
308 memcpy(&msg, data, len);
310 if (len != sizeof(NameServerMsg)) {
311 LOG1("NameServer: got bad NameServerMsg len (%d)\n",
312 len)
313 }
314 else {
315 LOG1("listener_cb: read from MessageQCopy 0x%x\n", handle)
316 LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
317 len, src)
318 LOG1("from vproc: %d\n", srcProc)
319 NameServerRemote_processMessage(&msg, srcProc);
320 }
321 }
323 /* =============================================================================
324 * APIS
325 * =============================================================================
326 */
328 /* Function to setup the nameserver module. */
329 Int NameServer_setup(Void)
330 {
331 Int status = NameServer_S_SUCCESS;
332 UInt16 numProcs;
333 int fd[2];
335 pthread_mutex_lock(&NameServer_module->modGate);
337 LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
339 NameServer_module->refCount++;
341 if (NameServer_module->refCount > 1) {
342 LOG0("NameServer_setup: already setup\n")
343 status = NameServer_S_ALREADYSETUP;
344 goto exit;
345 }
347 numProcs = MultiProc_getNumProcessors();
349 if (pipe(fd) == -1) {
350 status = NameServer_E_FAIL;
351 LOG0("NameServer_setup: failed to create waitFd.\n")
352 goto exit;
353 }
354 NameServer_module->waitFdW = fd[1];
355 NameServer_module->waitFdR = fd[0];
357 /* Create the MessageQCopy for receiving messages from all remote proc */
358 NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
359 NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
361 if (NameServer_module->mq == NULL) {
362 status = NameServer_E_FAIL;
363 LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
364 goto exit;
365 }
367 /* Construct the list object */
368 CIRCLEQ_INIT(&NameServer_module->objList);
370 exit:
371 LOG1("NameServer_setup: exiting, refCount=%d\n", \
372 NameServer_module->refCount)
374 pthread_mutex_unlock(&NameServer_module->modGate);
376 return (status);
377 }
379 /*! Function to destroy the nameserver module. */
380 Int NameServer_destroy(void)
381 {
382 Int status = NameServer_S_SUCCESS;
384 pthread_mutex_lock(&NameServer_module->modGate);
386 LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
388 NameServer_module->refCount--;
390 if (NameServer_module->refCount > 0) {
391 LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
392 status = NameServer_S_SUCCESS;
394 goto exit;
395 }
397 /* Delete the MessageQCopy instances */
398 if (NameServer_module->mq != NULL) {
399 MessageQCopy_delete(&NameServer_module->mq);
400 }
402 CIRCLEQ_destruct(&NameServer_module->objList);
404 close(NameServer_module->waitFdW);
405 close(NameServer_module->waitFdR);
407 exit:
408 LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
410 pthread_mutex_unlock(&NameServer_module->modGate);
412 return (status);
413 }
415 /* Function to retrieve a NameServer handle from name. */
416 NameServer_Handle NameServer_getHandle(String name)
417 {
418 NameServer_Handle handle = NULL;
419 Bool found = FALSE;
420 struct NameServer_Object * elem;
422 assert(name != NULL);
423 assert(NameServer_module->refCount != 0);
425 pthread_mutex_lock(&NameServer_module->modGate);
427 /* Lookup handle from name: */
428 CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
429 handle = (NameServer_Handle) elem;
430 if (strcmp(handle->name, name) == 0) {
431 found = TRUE;
432 break;
433 }
434 }
436 if (found == FALSE) {
437 handle = NULL;
438 }
440 pthread_mutex_unlock(&NameServer_module->modGate);
442 return (handle);
443 }
446 /* Function to create a name server. */
447 NameServer_Handle NameServer_create(String name,
448 const NameServer_Params * params)
449 {
450 NameServer_Handle handle = NULL;
451 pthread_mutexattr_t mutex_attr;
453 assert(params != NULL);
454 assert(name != NULL);
455 assert(NameServer_module->refCount != 0);
457 LOG1("NameServer_create(): '%s'\n", name)
459 pthread_mutex_lock(&NameServer_module->modGate);
461 if (params->maxValueLen > sizeof(UInt32)) {
462 LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
463 /* Can't handle more than UInt32 at this time: */
464 goto leave;
465 }
467 /* check if the name is already created or not */
468 if (NameServer_getHandle(name)) {
469 LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
470 handle = NULL;
471 goto leave;
472 }
473 else {
474 handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
475 }
477 if (!handle) {
478 LOG0("NameServer_create: NameServer_Handle alloc failed\n")
479 goto leave;
480 }
482 handle->name = (String)malloc(strlen(name) + 1u);
483 if (!handle->name) {
484 LOG0("NameServer_create: instance name alloc failed\n")
485 goto cleanup;
486 }
487 strncpy(handle->name, name, strlen (name) + 1u);
488 memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
490 if (params->maxValueLen < sizeof(UInt32)) {
491 handle->params.maxValueLen = sizeof(UInt32);
492 }
493 else {
494 handle->params.maxValueLen = params->maxValueLen;
495 }
497 CIRCLEQ_INIT(&handle->nameList);
498 handle->count = 0u;
500 /* Put in the local list */
501 CIRCLEQ_elemClear(&handle->elem);
502 CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
504 /*
505 * NameServer_removeEntry() enters gate and is called by
506 * NameServer_remove() while holding the gate.
507 */
508 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
509 pthread_mutex_init(&handle->gate, &mutex_attr);
511 goto leave;
513 cleanup:
514 free(handle);
515 handle = NULL;
517 leave:
518 pthread_mutex_unlock(&NameServer_module->modGate);
520 return (handle);
521 }
524 /* Function to delete a name server. */
525 Int NameServer_delete(NameServer_Handle * handle)
526 {
527 Int status = NameServer_S_SUCCESS;
529 assert(handle != NULL);
530 assert(*handle != NULL);
531 assert((*handle)->count == 0);
532 assert(NameServer_module->refCount != 0);
534 pthread_mutex_lock(&NameServer_module->modGate);
536 if ((*handle)->count == 0) {
537 CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
539 if ((*handle)->name != NULL) {
540 free((*handle)->name);
541 (*handle)->name = NULL;
542 }
544 CIRCLEQ_destruct(&(*handle)->nameList);
546 free((*handle));
547 (*handle) = NULL;
548 }
550 pthread_mutex_unlock(&NameServer_module->modGate);
552 return (status);
553 }
555 /* Adds a variable length value into the local NameServer table */
556 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
557 {
558 Int status = NameServer_S_SUCCESS;
559 NameServer_TableEntry * node = NULL;
560 NameServer_TableEntry * new_node = NULL;
561 Bool found = FALSE;
562 UInt32 hash;
564 assert(handle != NULL);
565 assert(name != NULL);
566 assert(buf != NULL);
567 assert(len != 0);
568 assert(NameServer_module->refCount != 0);
570 /* Calculate the hash */
571 hash = stringHash(name);
573 pthread_mutex_lock(&handle->gate);
575 /* Traverse the list to find duplicate check */
576 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
577 /* Hash matches */
578 if (node->hash == hash) {
579 /* If the name matches, incase hash is duplicate */
580 if (strcmp(node->name, name) == 0) {
581 if (handle->params.checkExisting == TRUE) {
582 status = NameServer_E_INVALIDARG;
583 LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
584 break;
585 }
586 }
587 else {
588 found = TRUE;
589 break;
590 } /* name does not match */
591 } /* hash does not match */
592 } /* CIRCLEQ_traverse */
594 if (status != NameServer_S_SUCCESS) {
595 new_node = NULL;
596 goto exit;
597 }
599 /* Now add the new entry. */
600 new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
601 if (new_node == NULL) {
602 status = NameServer_E_MEMORY;
603 LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
605 goto exit;
606 }
608 new_node->hash = hash;
609 new_node->collide = found; /* Indicate if there is a collision*/
610 new_node->len = len;
611 new_node->next = NULL;
612 new_node->name = (String)malloc(strlen(name) + 1u);
613 new_node->value = (Ptr)malloc(len);
614 strncpy(new_node->name, name, strlen(name) + 1u);
615 memcpy((Ptr)new_node->value, (Ptr)buf, len);
617 if (found == TRUE) {
618 /* If hash is found, need to stitch the list to link the
619 * new node to the existing node with the same hash.
620 */
621 new_node->next = node->next;
622 node->next = new_node;
623 }
624 else {
625 /* put the new node into the list */
626 CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
627 }
629 handle->count++;
631 LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
632 name, *(UInt32 *)buf)
634 exit:
635 pthread_mutex_unlock(&handle->gate);
637 return (new_node);
638 }
641 /* Function to add a UInt32 value into a name server. */
642 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
643 {
644 Ptr entry = NULL;
646 assert(handle != NULL);
647 assert(name != NULL);
648 assert(NameServer_module->refCount != 0);
650 entry = NameServer_add(handle, name, &value, sizeof(UInt32));
652 return (entry);
653 }
655 /* Function to remove a name/value pair from a name server. */
656 Int NameServer_remove(NameServer_Handle handle, String name)
657 {
658 Int status = NameServer_S_SUCCESS;
659 NameServer_TableEntry *prev = NULL;
660 NameServer_TableEntry *temp = NULL;
661 NameServer_TableEntry *node = NULL;
662 Bool done = FALSE;
663 UInt32 hash;
665 assert(handle != NULL);
666 assert(name != NULL);
667 assert(NameServer_module->refCount != 0);
669 /* Calculate the hash */
670 hash = stringHash(name);
672 pthread_mutex_lock(&handle->gate);
674 /* Traverse the list to find duplicate check */
675 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
676 /* Hash matchs */
677 if (node->hash == hash) {
678 if (node->collide == TRUE) {
679 if (strcmp(node->name, name) == 0){
680 free(node->value);
681 free(node->name);
682 memcpy((Ptr)node, (Ptr) node->next,
683 sizeof(NameServer_TableEntry));
684 node->next = node->next->next;
685 free(node->next);
686 handle->count--;
687 done = TRUE;
688 break;
689 }
690 else {
691 prev = node;
692 temp = node->next;
693 while (temp) {
694 if (strcmp(temp->name, name) == 0){
695 free(temp->value);
696 free(temp->name);
697 prev->next = temp->next;
698 free(temp);
699 handle->count--;
700 done = TRUE;
701 break;
702 }
703 temp = temp->next;
704 }
705 break;
706 }
707 }
708 else {
709 NameServer_removeEntry(handle, (Ptr)node);
711 done = TRUE;
712 break;
713 }
714 }
715 }
717 if (done == FALSE) {
718 status = NameServer_E_INVALIDARG;
719 LOG1("NameServer_remove %d Entry not found!\n", status)
720 }
722 pthread_mutex_unlock(&handle->gate);
724 return (status);
725 }
727 /* Function to remove a name/value pair from a name server. */
728 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
729 {
730 Int status = NameServer_S_SUCCESS;
731 NameServer_TableEntry * node;
733 assert(handle != NULL);
734 assert(entry != NULL);
735 assert(NameServer_module->refCount != 0);
737 pthread_mutex_lock(&handle->gate);
739 node = (NameServer_TableEntry *)entry;
741 free(node->value);
742 free(node->name);
743 CIRCLEQ_REMOVE(&handle->nameList, node, elem);
744 free(node);
745 handle->count--;
747 pthread_mutex_unlock(&handle->gate);
749 return (status);
750 }
753 /* Initialize this config-params structure with supplier-specified
754 * defaults before instance creation.
755 */
756 Void NameServer_Params_init(NameServer_Params * params)
757 {
758 assert(params != NULL);
760 memcpy(params, &(NameServer_module->defInstParams),
761 sizeof (NameServer_Params));
762 }
765 Int NameServer_getRemote(NameServer_Handle handle,
766 String name,
767 Ptr value,
768 UInt32 * len,
769 UInt16 procId)
770 {
771 Int status = NameServer_S_SUCCESS;
772 Int mqcStatus = -1;
773 struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
774 NameServerMsg nsMsg;
775 NameServerMsg *replyMsg;
776 fd_set rfds;
777 int ret = 0, maxfd, waitFd;
778 struct timeval tv;
779 char buf = '1';
780 int numBytes;
782 pthread_mutex_lock(&NameServer_module->modGate);
784 /* Set Timeout to wait: */
785 tv.tv_sec = NAMESERVER_GET_TIMEOUT;
786 tv.tv_usec = 0;
788 /* Create request message and send to remote processor: */
789 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
790 nsMsg.request = NAMESERVER_REQUEST;
791 nsMsg.requestStatus = 0;
793 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
794 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
796 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
797 procId, (String)nsMsg.instanceName)
798 LOG1("%s...\n", (String)nsMsg.name)
799 /* send message */
800 mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
801 RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
802 TRUE);
803 if (mqcStatus < 0) {
804 LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
805 status = NameServer_E_NOTFOUND;
806 goto exit;
807 }
809 /* Block on waitFd for signal from listener thread: */
810 waitFd = NameServer_module->waitFdR;
811 FD_ZERO(&rfds);
812 FD_SET(waitFd, &rfds);
813 maxfd = waitFd + 1;
814 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
815 ret = select(maxfd, &rfds, NULL, NULL, &tv);
816 if (ret == -1) {
817 LOG0("NameServer_getRemote: select failed.")
818 status = NameServer_E_FAIL;
819 goto exit;
820 }
821 else if (!ret) {
822 LOG0("NameServer_getRemote: select timed out.\n")
823 status = NameServer_E_TIMEOUT;
824 goto exit;
825 }
827 if (FD_ISSET(waitFd, &rfds)) {
828 /* Read, just to balance the write: */
829 numBytes = read(waitFd, &buf, sizeof(buf));
831 /* Process response: */
832 replyMsg = &NameServer_module->nsMsg;
834 if (replyMsg->requestStatus) {
835 /* name is found */
836 /* set the contents of value */
837 *(UInt32 *)value = (UInt32)replyMsg->value;
839 LOG2("NameServer_getRemote: Reply from: %d, %s:",
840 procId, (String)replyMsg->instanceName)
841 LOG2("%s, value: 0x%x...\n",
842 (String)replyMsg->name, *(UInt32 *)value)
843 goto exit;
844 }
845 else {
846 /* name is not found */
847 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
848 (String)replyMsg->instanceName, (String)replyMsg->name)
850 /* set status to not found */
851 status = NameServer_E_NOTFOUND;
852 }
853 }
855 exit:
856 pthread_mutex_unlock(&NameServer_module->modGate);
858 return (status);
859 }
861 /* Function to retrieve the value portion of a name/value pair from
862 * local table.
863 */
864 Int NameServer_get(NameServer_Handle handle,
865 String name,
866 Ptr value,
867 UInt32 * len,
868 UInt16 procId[])
869 {
870 Int status = NameServer_S_SUCCESS;
871 UInt16 numProcs = MultiProc_getNumProcessors();
872 UInt32 i;
874 if (procId == NULL) {
875 status = NameServer_getLocal(handle, name, value, len);
876 if (status == NameServer_E_NOTFOUND) {
877 for (i = 0; i < numProcs; i++) {
878 /* getLocal call already covers "self", keep going */
879 if (i == MultiProc_self()) {
880 continue;
881 }
883 status = NameServer_getRemote(handle, name, value, len, i);
885 if ((status >= 0) ||
886 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
887 break;
888 }
889 }
890 }
891 }
892 else {
893 /*
894 * Search the query list. It might contain the local proc
895 * somewhere in the list.
896 */
897 i = 0;
898 while (procId[i] != MultiProc_INVALIDID) {
899 if (procId[i] == MultiProc_self()) {
900 status = NameServer_getLocal(handle, name, value, len);
901 }
902 else {
903 status = NameServer_getRemote(handle, name, value, len, i);
904 }
906 if ((status >= 0) ||
907 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
908 break;
909 }
911 i++;
912 }
913 }
915 return (status);
916 }
918 /* Gets a 32-bit value by name */
919 Int NameServer_getUInt32(NameServer_Handle handle,
920 String name,
921 Ptr value,
922 UInt16 procId[])
923 {
924 Int status;
925 UInt32 len = sizeof(UInt32);
927 assert(handle != NULL);
928 assert(name != NULL);
929 assert(value != NULL);
930 assert(NameServer_module->refCount != 0);
932 status = NameServer_get(handle, name, value, &len, procId);
934 return (status);
935 }
937 /* Function to Retrieve the value portion of a name/value pair from
938 * local table.
939 */
940 Int NameServer_getLocal(NameServer_Handle handle,
941 String name,
942 Ptr value,
943 UInt32 * len)
944 {
945 Int status = NameServer_E_NOTFOUND;
946 NameServer_TableEntry * node = NULL;
947 NameServer_TableEntry * temp = NULL;
948 Bool done = FALSE;
949 UInt32 length;
950 UInt32 hash;
952 assert(handle != NULL);
953 assert(name != NULL);
954 assert(value != NULL);
955 assert(len != NULL);
956 assert(NameServer_module->refCount != 0);
958 length = *len;
960 /* Calculate the hash */
961 hash = stringHash(name);
963 pthread_mutex_lock(&handle->gate);
965 /* Traverse the list to find duplicate check */
966 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
967 if (node->hash == hash) {
968 if (node->collide == TRUE) {
969 temp = node;
970 while (temp) {
971 if (strcmp(temp->name, name) == 0u){
972 if (length <= node->len) {
973 memcpy(value, node->value, length);
974 *len = length;
975 }
976 else {
977 memcpy(value, node->value, node->len);
978 *len = node->len;
979 }
980 done = TRUE;
981 break;
982 }
983 temp = temp->next;
984 }
985 break;
986 }
987 else {
988 if (length <= node->len) {
989 memcpy(value, node->value, length);
990 *len = length;
991 }
992 else {
993 memcpy(value, node->value, node->len);
994 *len = node->len;
995 }
996 done = TRUE;
997 break;
998 }
999 }
1000 }
1002 pthread_mutex_unlock(&handle->gate);
1004 if (done == FALSE) {
1005 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1006 }
1007 else {
1008 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1009 node->name, (UInt32)node->value)
1010 status = NameServer_S_SUCCESS;
1011 }
1013 return (status);
1014 }
1016 /*
1017 * Gets a 32-bit value by name from the local table
1018 *
1019 * If the name is found, the 32-bit value is copied into the value
1020 * argument and a success status is returned.
1021 *
1022 * If the name is not found, zero is returned in len and the contents
1023 * of value are not modified. Not finding a name is not considered
1024 * an error.
1025 *
1026 * This function only searches the local name/value table.
1027 *
1028 */
1029 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1030 {
1031 Int status;
1032 UInt32 len = sizeof(UInt32);
1034 assert(handle != NULL);
1035 assert(name != NULL);
1036 assert(value != NULL);
1037 assert(NameServer_module->refCount != 0);
1039 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1040 status = NameServer_getLocal(handle, name, value, &len);
1042 return (status);
1043 }
1046 #if defined (__cplusplus)
1047 }
1048 #endif /* defined (__cplusplus) */