This is Unofficial EPICS BASE Doxygen Site
dbPvdLib.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 
10 /* dbPvdLib.c */
11 
12 #include <stddef.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 
17 #include "dbDefs.h"
18 #include "ellLib.h"
19 #include "epicsMutex.h"
20 #include "epicsStdio.h"
21 #include "epicsString.h"
22 
23 #define epicsExportSharedSymbols
24 #include "dbBase.h"
25 #include "dbStaticLib.h"
26 #include "dbStaticPvt.h"
27 
28 typedef struct {
31 } dbPvdBucket;
32 
33 typedef struct dbPvd {
34  unsigned int size;
35  unsigned int mask;
37 } dbPvd;
38 
39 unsigned int dbPvdHashTableSize = 0;
40 
41 #define MIN_SIZE 256
42 #define DEFAULT_SIZE 512
43 #define MAX_SIZE 65536
44 
45 
47 {
48  if (size & (size - 1)) {
49  printf("dbPvdTableSize: %d is not a power of 2\n", size);
50  return -1;
51  }
52 
53  if (size < MIN_SIZE)
54  size = MIN_SIZE;
55 
56  if (size > MAX_SIZE)
57  size = MAX_SIZE;
58 
60  return 0;
61 }
62 
63 void dbPvdInitPvt(dbBase *pdbbase)
64 {
65  dbPvd *ppvd;
66 
67  if (pdbbase->ppvd) return;
68 
69  if (dbPvdHashTableSize == 0) {
71  }
72 
73  ppvd = (dbPvd *)dbMalloc(sizeof(dbPvd));
74  ppvd->size = dbPvdHashTableSize;
75  ppvd->mask = dbPvdHashTableSize - 1;
76  ppvd->buckets = dbCalloc(ppvd->size, sizeof(dbPvdBucket *));
77 
78  pdbbase->ppvd = ppvd;
79  return;
80 }
81 
82 PVDENTRY *dbPvdFind(dbBase *pdbbase, const char *name, size_t lenName)
83 {
84  dbPvd *ppvd = pdbbase->ppvd;
85  dbPvdBucket *pbucket;
86  PVDENTRY *ppvdNode;
87 
88  pbucket = ppvd->buckets[epicsMemHash(name, lenName, 0) & ppvd->mask];
89  if (pbucket == NULL) return NULL;
90 
91  epicsMutexMustLock(pbucket->lock);
92  ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
93  while (ppvdNode) {
94  const char *recordname = ppvdNode->precnode->recordname;
95 
96  if (strncmp(name, recordname, lenName) == 0 &&
97  strlen(recordname) == lenName)
98  break;
99  ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode);
100  }
101  epicsMutexUnlock(pbucket->lock);
102  return ppvdNode;
103 }
104 
105 PVDENTRY *dbPvdAdd(dbBase *pdbbase, dbRecordType *precordType,
106  dbRecordNode *precnode)
107 {
108  dbPvd *ppvd = pdbbase->ppvd;
109  dbPvdBucket *pbucket;
110  PVDENTRY *ppvdNode;
111  char *name = precnode->recordname;
112  unsigned int h;
113 
114  h = epicsStrHash(name, 0) & ppvd->mask;
115  pbucket = ppvd->buckets[h];
116  if (pbucket == NULL) {
117  pbucket = dbCalloc(1, sizeof(dbPvdBucket));
118  ellInit(&pbucket->list);
119  pbucket->lock = epicsMutexCreate();
120  ppvd->buckets[h] = pbucket;
121  }
122 
123  epicsMutexMustLock(pbucket->lock);
124  ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
125  while (ppvdNode) {
126  if (strcmp(name, ppvdNode->precnode->recordname) == 0) {
127  epicsMutexUnlock(pbucket->lock);
128  return NULL;
129  }
130  ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode);
131  }
132  ppvdNode = dbCalloc(1, sizeof(PVDENTRY));
133  ppvdNode->precordType = precordType;
134  ppvdNode->precnode = precnode;
135  ellAdd(&pbucket->list, (ELLNODE *)ppvdNode);
136  epicsMutexUnlock(pbucket->lock);
137  return ppvdNode;
138 }
139 
140 void dbPvdDelete(dbBase *pdbbase, dbRecordNode *precnode)
141 {
142  dbPvd *ppvd = pdbbase->ppvd;
143  dbPvdBucket *pbucket;
144  PVDENTRY *ppvdNode;
145  char *name = precnode->recordname;
146 
147  pbucket = ppvd->buckets[epicsStrHash(name, 0) & ppvd->mask];
148  if (pbucket == NULL) return;
149 
150  epicsMutexMustLock(pbucket->lock);
151  ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
152  while (ppvdNode) {
153  if (ppvdNode->precnode &&
154  ppvdNode->precnode->recordname &&
155  strcmp(name, ppvdNode->precnode->recordname) == 0) {
156  ellDelete(&pbucket->list, (ELLNODE *)ppvdNode);
157  free(ppvdNode);
158  break;
159  }
160  ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode);
161  }
162  epicsMutexUnlock(pbucket->lock);
163  return;
164 }
165 
166 void dbPvdFreeMem(dbBase *pdbbase)
167 {
168  dbPvd *ppvd = pdbbase->ppvd;
169  unsigned int h;
170 
171  if (ppvd == NULL) return;
172  pdbbase->ppvd = NULL;
173 
174  for (h = 0; h < ppvd->size; h++) {
175  dbPvdBucket *pbucket = ppvd->buckets[h];
176  PVDENTRY *ppvdNode;
177 
178  if (pbucket == NULL) continue;
179  epicsMutexMustLock(pbucket->lock);
180  ppvd->buckets[h] = NULL;
181  while ((ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list))) {
182  ellDelete(&pbucket->list, (ELLNODE *)ppvdNode);
183  free(ppvdNode);
184  }
185  epicsMutexUnlock(pbucket->lock);
186  epicsMutexDestroy(pbucket->lock);
187  free(pbucket);
188  }
189  free(ppvd->buckets);
190  free(ppvd);
191 }
192 
193 void dbPvdDump(dbBase *pdbbase, int verbose)
194 {
195  unsigned int empty = 0;
196  dbPvd *ppvd;
197  unsigned int h;
198 
199  if (!pdbbase) {
200  fprintf(stderr,"pdbbase not specified\n");
201  return;
202  }
203  ppvd = pdbbase->ppvd;
204  if (ppvd == NULL) return;
205 
206  printf("Process Variable Directory has %u buckets", ppvd->size);
207 
208  for (h = 0; h < ppvd->size; h++) {
209  dbPvdBucket *pbucket = ppvd->buckets[h];
210  PVDENTRY *ppvdNode;
211  int i = 1;
212 
213  if (pbucket == NULL) {
214  empty++;
215  continue;
216  }
217  epicsMutexMustLock(pbucket->lock);
218  ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
219  printf("\n [%4u] %4d ", h, ellCount(&pbucket->list));
220  while (ppvdNode && verbose) {
221  if (!(++i % 4))
222  printf("\n ");
223  printf(" %s", ppvdNode->precnode->recordname);
224  ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode);
225  }
226  epicsMutexUnlock(pbucket->lock);
227  }
228  printf("\n%u buckets empty.\n", empty);
229 }
unsigned int epicsStrHash(const char *str, unsigned int seed)
Definition: epicsString.c:356
struct dbPvd dbPvd
epics::pvData::BitSetPtr empty
Definition: pvAccess.cpp:135
void dbPvdDump(dbBase *pdbbase, int verbose)
Definition: dbPvdLib.c:193
#define MAX_SIZE
Definition: dbPvdLib.c:43
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
PVDENTRY * dbPvdAdd(dbBase *pdbbase, dbRecordType *precordType, dbRecordNode *precnode)
Definition: dbPvdLib.c:105
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
Destroy an epicsMutex semaphore.
Definition: epicsMutex.cpp:127
int i
Definition: scan.c:967
#define printf
Definition: epicsStdio.h:41
void dbPvdFreeMem(dbBase *pdbbase)
Definition: dbPvdLib.c:166
unsigned int mask
Definition: dbPvdLib.c:35
#define NULL
Definition: catime.c:38
dbPvdBucket ** buckets
Definition: dbPvdLib.c:36
void dbPvdDelete(dbBase *pdbbase, dbRecordNode *precnode)
Definition: dbPvdLib.c:140
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
Miscellaneous macro definitions.
struct dbPvd * ppvd
Definition: dbBase.h:182
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
#define DEFAULT_SIZE
Definition: dbPvdLib.c:42
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
unsigned int size
Definition: dbPvdLib.c:34
unsigned int dbPvdHashTableSize
Definition: dbPvdLib.c:39
ELLLIST list
Definition: dbPvdLib.c:29
APIs for the epicsMutex mutual exclusion semaphore.
#define dbMalloc(size)
Definition: dbStaticLib.h:229
PVDENTRY * dbPvdFind(dbBase *pdbbase, const char *name, size_t lenName)
Definition: dbPvdLib.c:82
#define MIN_SIZE
Definition: dbPvdLib.c:41
List node type.
Definition: ellLib.h:45
dbRecordNode * precnode
Definition: dbStaticPvt.h:98
Definition: dbPvdLib.c:33
#define dbCalloc(nobj, size)
Definition: dbStaticLib.h:228
unsigned int epicsMemHash(const char *str, size_t length, unsigned int seed)
Definition: epicsString.c:369
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
void verbose(void)
Definition: verbose.c:27
#define epicsMutexCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:168
Definition: dbBase.h:170
dbRecordType * precordType
Definition: dbStaticPvt.h:97
char * recordname
Definition: dbBase.h:117
void dbPvdInitPvt(dbBase *pdbbase)
Definition: dbPvdLib.c:63
#define stderr
Definition: epicsStdio.h:32
List header type.
Definition: ellLib.h:56
epicsMutexId lock
Definition: dbPvdLib.c:30
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
int dbPvdTableSize(int size)
Definition: dbPvdLib.c:46
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89