Reworked various hash tables, using the faster epicsStrHash() routines;

added per-bucket locks to the PV Directory, needed for run-time alias creation;
speed up gpHash lookups; improved the output of both Dump routines.
This commit is contained in:
Andrew Johnson
2009-03-19 23:00:44 +00:00
parent 7eeb70a8d9
commit 7ce49bf131
6 changed files with 314 additions and 358 deletions

View File

@@ -126,12 +126,14 @@ epicsShareExtern int asActive;
/* definition of access rights*/
typedef enum{asNOACCESS,asREAD,asWRITE} asAccessRights;
struct gphPvt;
/*Base pointers for access security*/
typedef struct asBase{
ELLLIST uagList;
ELLLIST hagList;
ELLLIST asgList;
void *phash;
struct gphPvt *phash;
} ASBASE;
epicsShareExtern volatile ASBASE *pasbase;

View File

@@ -113,7 +113,7 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
pasg->pavalue = asCalloc(CALCPERFORM_NARGS, sizeof(double));
pasg = (ASG *)ellNext((ELLNODE *)pasg);
}
gphInitPvt(&((ASBASE *)pasbasenew)->phash,256);
gphInitPvt(&pasbasenew->phash, 256);
/*Hash each uagname and each hagname*/
puag = (UAG *)ellFirst(&pasbasenew->uagList);
while(puag) {

View File

@@ -140,7 +140,7 @@ typedef struct dbRecordType {
short no_fields; /* number of fields defined */
short no_prompt; /* number of fields to configure*/
short no_links; /* number of links */
short no_aliases;
short no_aliases; /* number of aliases in recList */
short *link_ind; /* addr of array of ind in papFldDes*/
char **papsortFldName;/* ptr to array of ptr to fld names*/
short *sortFldInd; /* addr of array of ind in papFldDes*/
@@ -152,6 +152,9 @@ typedef struct dbRecordType {
int rec_size; /*record size in bytes */
}dbRecordType;
struct dbPvd; /* Contents private to dbPvdLib code */
struct gphPvt; /* Contents private to gpHashLib code */
typedef struct dbBase {
ELLLIST menuList;
ELLLIST recordTypeList;
@@ -159,10 +162,10 @@ typedef struct dbBase {
ELLLIST registrarList;
ELLLIST functionList;
ELLLIST variableList;
ELLLIST bptList; /*Break Point Table Head*/
ELLLIST bptList;
void *pathPvt;
void *ppvd; /* pointer to process variable directory*/
void *pgpHash; /*General purpose Hash Table*/
struct dbPvd *ppvd;
struct gphPvt *pgpHash;
short ignoreMissingMenus;
short loadCdefs;
}dbBase;

View File

@@ -1,5 +1,5 @@
/*************************************************************************\
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
@@ -13,241 +13,215 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include "dbDefs.h"
#include "ellLib.h"
#include "dbBase.h"
#include "epicsStdio.h"
#include "epicsString.h"
#include "epicsMutex.h"
#define epicsExportSharedSymbols
#include "dbStaticLib.h"
#include "dbStaticPvt.h"
int dbPvdHashTableSize = 512;
static int dbPvdHashTableShift;
#define NTABLESIZES 9
static struct {
unsigned int tablesize;
int shift;
}hashTableParms[9] = {
{256,0},
{512,1},
{1024,2},
{2048,3},
{4096,4},
{8192,5},
{16384,6},
{32768,7},
{65536,8}
};
typedef struct {
ELLLIST list;
epicsMutexId lock;
} dbPvdBucket;
/*The hash algorithm is a modification of the algorithm described in */
/* Fast Hashing of Variable Length Text Strings, Peter K. Pearson, */
/* Communications of the ACM, June 1990 */
/* The modifications were designed by Marty Kraimer */
typedef struct dbPvd {
unsigned int size;
unsigned int mask;
dbPvdBucket **buckets;
} dbPvd;
static unsigned char T[256] = {
39,159,180,252, 71, 6, 13,164,232, 35,226,155, 98,120,154, 69,
157, 24,137, 29,147, 78,121, 85,112, 8,248,130, 55,117,190,160,
176,131,228, 64,211,106, 38, 27,140, 30, 88,210,227,104, 84, 77,
75,107,169,138,195,184, 70, 90, 61,166, 7,244,165,108,219, 51,
9,139,209, 40, 31,202, 58,179,116, 33,207,146, 76, 60,242,124,
254,197, 80,167,153,145,129,233,132, 48,246, 86,156,177, 36,187,
45, 1, 96, 18, 19, 62,185,234, 99, 16,218, 95,128,224,123,253,
42,109, 4,247, 72, 5,151,136, 0,152,148,127,204,133, 17, 14,
182,217, 54,199,119,174, 82, 57,215, 41,114,208,206,110,239, 23,
189, 15, 3, 22,188, 79,113,172, 28, 2,222, 21,251,225,237,105,
102, 32, 56,181,126, 83,230, 53,158, 52, 59,213,118,100, 67,142,
220,170,144,115,205, 26,125,168,249, 66,175, 97,255, 92,229, 91,
214,236,178,243, 46, 44,201,250,135,186,150,221,163,216,162, 43,
11,101, 34, 37,194, 25, 50, 12, 87,198,173,240,193,171,143,231,
111,141,191,103, 74,245,223, 20,161,235,122, 63, 89,149, 73,238,
134, 68, 93,183,241, 81,196, 49,192, 65,212, 94,203, 10,200, 47
};
unsigned int dbPvdHashTableSize = 0;
static unsigned short hash( const char *pname, int length)
#define MIN_SIZE 256
#define DEFAULT_SIZE 512
#define MAX_SIZE 65536
int dbPvdTableSize(int size)
{
unsigned char h0=0;
unsigned char h1=0;
unsigned short ind0,ind1;
int isOdd;
int i,n;
isOdd = length%2; /*See if length is odd number of chanacters*/
n = (isOdd ? (length-1) : length);
if(isOdd) h0 = T[h0^*(pname + length -1)];
for(i=0; i<n; i+=2, pname+=2) {
h0 = T[h0^*pname];
h1 = T[h1^*(pname+1)];
if (size & (size - 1)) {
printf("dbPvdTableSize: %d is not a power of 2\n", size);
return -1;
}
ind0 = (unsigned short)h0;
ind1 = (unsigned short)h1;
return((ind1<<dbPvdHashTableShift) ^ ind0);
if (size < MIN_SIZE)
size = MIN_SIZE;
if (size > MAX_SIZE)
size = MAX_SIZE;
dbPvdHashTableSize = size;
return 0;
}
int epicsShareAPI dbPvdTableSize(int size)
void dbPvdInitPvt(dbBase *pdbbase)
{
int i;
dbPvd *ppvd;
for(i=0; i< NTABLESIZES; i++) {
if(size==hashTableParms[i].tablesize) {
dbPvdHashTableSize = hashTableParms[i].tablesize;
dbPvdHashTableShift = hashTableParms[i].shift;
return(0);
}
if (pdbbase->ppvd) return;
if (dbPvdHashTableSize == 0) {
dbPvdHashTableSize = DEFAULT_SIZE;
}
printf("Illegal Size for Process Variable Directory\n");
return(-1);
}
ppvd = (dbPvd *)dbMalloc(sizeof(dbPvd));
ppvd->size = dbPvdHashTableSize;
ppvd->mask = dbPvdHashTableSize - 1;
ppvd->buckets = dbCalloc(ppvd->size, sizeof(dbPvdBucket *));
void dbPvdInitPvt(dbBase *pdbbase)
{
ELLLIST **ppvd;
int i;
for(i=0; i< NTABLESIZES; i++) {
if((i==NTABLESIZES-1)
||((dbPvdHashTableSize>=hashTableParms[i].tablesize)
&& (dbPvdHashTableSize<hashTableParms[i+1].tablesize))) {
dbPvdHashTableSize = hashTableParms[i].tablesize;
dbPvdHashTableShift = hashTableParms[i].shift;
break;
}
}
ppvd = dbCalloc(dbPvdHashTableSize, sizeof(ELLLIST *));
pdbbase->ppvd = (void *) ppvd;
pdbbase->ppvd = ppvd;
return;
}
PVDENTRY *dbPvdFind(dbBase *pdbbase, const char *name, int lenName)
{
unsigned short hashInd;
ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd;
ELLLIST *pvdlist;
PVDENTRY *ppvdNode;
dbPvd *ppvd = pdbbase->ppvd;
dbPvdBucket *pbucket;
PVDENTRY *ppvdNode;
hashInd = hash(name, lenName);
pvdlist = ppvd[hashInd];
if (pvdlist == NULL) return NULL;
ppvdNode = (PVDENTRY *) ellFirst(pvdlist);
pbucket = ppvd->buckets[epicsMemHash(name, lenName, 0) & ppvd->mask];
if (pbucket == NULL) return NULL;
epicsMutexMustLock(pbucket->lock);
ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
while (ppvdNode) {
if (strncmp(name, ppvdNode->precnode->recordname, lenName) == 0)
return ppvdNode;
ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode);
const char *recordname = ppvdNode->precnode->recordname;
if (strncmp(name, recordname, lenName) == 0 &&
strlen(recordname) == lenName)
break;
ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode);
}
return NULL;
epicsMutexUnlock(pbucket->lock);
return ppvdNode;
}
PVDENTRY *dbPvdAdd(dbBase *pdbbase, dbRecordType *precordType, dbRecordNode *precnode)
PVDENTRY *dbPvdAdd(dbBase *pdbbase, dbRecordType *precordType,
dbRecordNode *precnode)
{
unsigned short hashInd;
ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd;
ELLLIST *ppvdlist;
PVDENTRY *ppvdNode;
int lenName;
char *name = precnode->recordname;
dbPvd *ppvd = pdbbase->ppvd;
dbPvdBucket *pbucket;
PVDENTRY *ppvdNode;
char *name = precnode->recordname;
unsigned int h;
lenName = strlen(name);
hashInd = hash(name, lenName);
ppvdlist = ppvd[hashInd];
if (ppvdlist == NULL) {
ppvdlist = dbCalloc(1, sizeof(ELLLIST));
ellInit(ppvdlist);
ppvd[hashInd] = ppvdlist;
h = epicsStrHash(name, 0) & ppvd->mask;
pbucket = ppvd->buckets[h];
if (pbucket == NULL) {
pbucket = dbCalloc(1, sizeof(dbPvdBucket));
ellInit(&pbucket->list);
pbucket->lock = epicsMutexCreate();
ppvd->buckets[h] = pbucket;
}
ppvdNode = (PVDENTRY *) ellFirst(ppvdlist);
epicsMutexMustLock(pbucket->lock);
ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
while (ppvdNode) {
if (strcmp(name, ppvdNode->precnode->recordname) == 0) return NULL;
if (strcmp(name, ppvdNode->precnode->recordname) == 0) {
epicsMutexUnlock(pbucket->lock);
return NULL;
}
ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode);
}
ppvdNode = dbCalloc(1, sizeof(PVDENTRY));
ppvdNode->precordType = precordType;
ppvdNode->precnode = precnode;
ellAdd(ppvdlist, (ELLNODE *)ppvdNode);
ellAdd(&pbucket->list, (ELLNODE *)ppvdNode);
epicsMutexUnlock(pbucket->lock);
return ppvdNode;
}
void dbPvdDelete(dbBase *pdbbase,dbRecordNode *precnode)
void dbPvdDelete(dbBase *pdbbase, dbRecordNode *precnode)
{
char *name=precnode->recordname;
unsigned short hashInd;
ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd;
ELLLIST *ppvdlist;
PVDENTRY *ppvdNode;
int lenName;
lenName=strlen(name);
hashInd = hash(name, lenName);
if (ppvd[hashInd] == NULL)return;
ppvdlist=ppvd[hashInd];
ppvdNode = (PVDENTRY *) ellFirst(ppvdlist);
while(ppvdNode) {
if(ppvdNode->precnode && ppvdNode->precnode->recordname
&& strcmp(name,(char *)ppvdNode->precnode->recordname) == 0) {
ellDelete(ppvdlist, (ELLNODE*)ppvdNode);
free((void *)ppvdNode);
return;
}
ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode);
dbPvd *ppvd = pdbbase->ppvd;
dbPvdBucket *pbucket;
PVDENTRY *ppvdNode;
char *name = precnode->recordname;
pbucket = ppvd->buckets[epicsStrHash(name, 0) & ppvd->mask];
if (pbucket == NULL) return;
epicsMutexMustLock(pbucket->lock);
ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
while (ppvdNode) {
if (ppvdNode->precnode &&
ppvdNode->precnode->recordname &&
strcmp(name, ppvdNode->precnode->recordname) == 0) {
ellDelete(&pbucket->list, (ELLNODE *)ppvdNode);
free(ppvdNode);
break;
}
ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode);
}
epicsMutexUnlock(pbucket->lock);
return;
}
void dbPvdFreeMem(dbBase *pdbbase)
{
unsigned short hashInd;
ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd;
ELLLIST *ppvdlist;
PVDENTRY *ppvdNode;
PVDENTRY *next;
dbPvd *ppvd = pdbbase->ppvd;
unsigned int h;
if (ppvd == NULL) return;
for (hashInd=0; hashInd<(unsigned short)dbPvdHashTableSize; hashInd++) {
if(ppvd[hashInd] == NULL) continue;
ppvdlist=ppvd[hashInd];
ppvdNode = (PVDENTRY *) ellFirst(ppvdlist);
while(ppvdNode) {
next = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode);
ellDelete(ppvdlist,(ELLNODE*)ppvdNode);
free((void *)ppvdNode);
ppvdNode = next;
}
free((void *)ppvd[hashInd]);
}
free((void *)ppvd);
pdbbase->ppvd = NULL;
for (h = 0; h < ppvd->size; h++) {
dbPvdBucket *pbucket = ppvd->buckets[h];
PVDENTRY *ppvdNode;
if (pbucket == NULL) continue;
epicsMutexMustLock(pbucket->lock);
ppvd->buckets[h] = NULL;
while ((ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list))) {
ellDelete(&pbucket->list, (ELLNODE *)ppvdNode);
free(ppvdNode);
}
epicsMutexDestroy(pbucket->lock);
free(pbucket);
}
free(ppvd->buckets);
free(ppvd);
}
void epicsShareAPI dbPvdDump(dbBase *pdbbase,int verbose)
void dbPvdDump(dbBase *pdbbase, int verbose)
{
unsigned short hashInd;
ELLLIST **ppvd;
ELLLIST *ppvdlist;
PVDENTRY *ppvdNode;
int number;
if(!pdbbase) {
unsigned int empty = 0;
dbPvd *ppvd;
unsigned int h;
if (!pdbbase) {
fprintf(stderr,"pdbbase not specified\n");
return;
}
ppvd = (ELLLIST **)pdbbase->ppvd;
ppvd = pdbbase->ppvd;
if (ppvd == NULL) return;
printf("Process Variable Directory\n");
printf("dbPvdHashTableSize %d dbPvdHashTableShift %d\n",
dbPvdHashTableSize,dbPvdHashTableShift);
for (hashInd=0; hashInd<(unsigned short)dbPvdHashTableSize; hashInd++) {
if(ppvd[hashInd] == NULL) continue;
ppvdlist=ppvd[hashInd];
ppvdNode = (PVDENTRY *) ellFirst(ppvdlist);
printf("\n%3.3hd=%3.3d ",hashInd,ellCount(ppvdlist));
number=0;
while(ppvdNode && verbose) {
printf(" %s",(char *)ppvdNode->precnode->recordname);
if(number++ ==2) {number=0;printf("\n ");}
ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode);
}
printf("Process Variable Directory has %u buckets", ppvd->size);
for (h = 0; h < ppvd->size; h++) {
dbPvdBucket *pbucket = ppvd->buckets[h];
PVDENTRY *ppvdNode;
int i = 1;
if (pbucket == NULL) {
empty++;
continue;
}
epicsMutexMustLock(pbucket->lock);
ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
printf("\n [%4u] %4d ", h, ellCount(&pbucket->list));
while (ppvdNode && verbose) {
if (!(++i % 4))
printf("\n ");
printf(" %s", ppvdNode->precnode->recordname);
ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode);
}
epicsMutexUnlock(pbucket->lock);
}
printf("\nEnd of Process Variable Directory\n");
printf("\n%u buckets empty.\n", empty);
}

View File

@@ -7,13 +7,13 @@
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* gpHash.h */
/* share/epicsH $Id$ */
/* $Id$ */
/* Author: Marty Kraimer Date: 04-07-94 */
/* gph provides a general purpose directory accessed via a hash table*/
#ifndef INCgpHashh
#define INCgpHashh 1
#ifndef INC_gpHash_H
#define INC_gpHash_H
#include "shareLib.h"
@@ -26,24 +26,27 @@ typedef struct{
void *userPvt; /*private for user*/
} GPHENTRY;
struct gphPvt;
#ifdef __cplusplus
extern "C" {
#endif
/*tableSize must be power of 2 in range 256 to 65536*/
epicsShareFunc void epicsShareAPI gphInitPvt(void **ppvt,int tableSize);
epicsShareFunc GPHENTRY * epicsShareAPI
gphFind(void *pvt,const char *name,void *pvtid);
epicsShareFunc GPHENTRY * epicsShareAPI
gphAdd(void *pvt,const char *name,void *pvtid);
epicsShareFunc void epicsShareAPI
gphDelete(void *pvt,const char *name,void *pvtid);
epicsShareFunc void epicsShareAPI gphFreeMem(void *pvt);
epicsShareFunc void epicsShareAPI gphDump(void *pvt);
epicsShareFunc void epicsShareAPI gphDumpFP(FILE *fp,void *pvt);
gphInitPvt(struct gphPvt **ppvt, int tableSize);
epicsShareFunc GPHENTRY * epicsShareAPI
gphFind(struct gphPvt *pvt, const char *name, void *pvtid);
epicsShareFunc GPHENTRY * epicsShareAPI
gphAdd(struct gphPvt *pvt, const char *name, void *pvtid);
epicsShareFunc void epicsShareAPI
gphDelete(struct gphPvt *pvt, const char *name, void *pvtid);
epicsShareFunc void epicsShareAPI gphFreeMem(struct gphPvt *pvt);
epicsShareFunc void epicsShareAPI gphDump(struct gphPvt *pvt);
epicsShareFunc void epicsShareAPI gphDumpFP(FILE *fp, struct gphPvt *pvt);
#ifdef __cplusplus
}
#endif
#endif /*INCgpHashh*/
#endif /* INC_gpHash_H */

View File

@@ -1,13 +1,13 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* $Id$ */
/* Author: Marty Kraimer Date: 04-07-94 */
#include <stdio.h>
@@ -18,240 +18,214 @@
#define epicsExportSharedSymbols
#include "cantProceed.h"
#include "epicsMutex.h"
#include "epicsString.h"
#include "dbDefs.h"
#include "ellLib.h"
#include "epicsPrint.h"
#include "gpHash.h"
typedef struct gphPvt {
int tableSize;
int nShift;
ELLLIST **paplist; /*pointer to array of pointers to ELLLIST */
int size;
unsigned int mask;
ELLLIST **paplist; /*pointer to array of pointers to ELLLIST */
epicsMutexId lock;
}gphPvt;
} gphPvt;
#define MIN_SIZE 256
#define DEFAULT_SIZE 512
#define MAX_SIZE 65536
/*The hash algorithm is the algorithm described in */
/* Fast Hashing of Variable Length Text Strings, Peter K. Pearson, */
/* Communications of the ACM, June 1990 */
static unsigned char T[256] = {
39,159,180,252, 71, 6, 13,164,232, 35,226,155, 98,120,154, 69,
157, 24,137, 29,147, 78,121, 85,112, 8,248,130, 55,117,190,160,
176,131,228, 64,211,106, 38, 27,140, 30, 88,210,227,104, 84, 77,
75,107,169,138,195,184, 70, 90, 61,166, 7,244,165,108,219, 51,
9,139,209, 40, 31,202, 58,179,116, 33,207,146, 76, 60,242,124,
254,197, 80,167,153,145,129,233,132, 48,246, 86,156,177, 36,187,
45, 1, 96, 18, 19, 62,185,234, 99, 16,218, 95,128,224,123,253,
42,109, 4,247, 72, 5,151,136, 0,152,148,127,204,133, 17, 14,
182,217, 54,199,119,174, 82, 57,215, 41,114,208,206,110,239, 23,
189, 15, 3, 22,188, 79,113,172, 28, 2,222, 21,251,225,237,105,
102, 32, 56,181,126, 83,230, 53,158, 52, 59,213,118,100, 67,142,
220,170,144,115,205, 26,125,168,249, 66,175, 97,255, 92,229, 91,
214,236,178,243, 46, 44,201,250,135,186,150,221,163,216,162, 43,
11,101, 34, 37,194, 25, 50, 12, 87,198,173,240,193,171,143,231,
111,141,191,103, 74,245,223, 20,161,235,122, 63, 89,149, 73,238,
134, 68, 93,183,241, 81,196, 49,192, 65,212, 94,203, 10,200, 47
};
#define NSIZES 9
static int allowSize[NSIZES] = {256,512,1024,2048,4096,8192,16384,32768,65536};
static int hash(const char *pname,int nShift)
{
unsigned char h0=0;
unsigned char h1=0;
unsigned short ind0,ind1;
int even = TRUE;
unsigned char c;
while(*pname) {
c = *pname;
if(even) {h0 = T[h0^c]; even = FALSE;}
else {h1 = T[h1^c]; even = TRUE;}
pname++;
}
ind0 = (unsigned short)h0;
ind1 = (unsigned short)h1;
return((ind1<<nShift) ^ ind0);
}
void epicsShareAPI gphInitPvt(void **ppvt,int size)
void epicsShareAPI gphInitPvt(gphPvt **ppvt, int size)
{
gphPvt *pgphPvt;
int i;
int tableSize=0;
int nShift=0;
for(i=0; i<NSIZES; i++) {
if(size==allowSize[i]) {
tableSize = size;
nShift = i;
}
}
if(tableSize==0) {
epicsPrintf("gphInitPvt: Illegal size\n");
return;
if (size & (size - 1)) {
printf("gphInitPvt: %d is not a power of 2\n", size);
size = DEFAULT_SIZE;
}
if (size < MIN_SIZE)
size = MIN_SIZE;
if (size > MAX_SIZE)
size = MAX_SIZE;
pgphPvt = callocMustSucceed(1, sizeof(gphPvt), "gphInitPvt");
pgphPvt->tableSize = tableSize;
pgphPvt->nShift = nShift;
pgphPvt->paplist = callocMustSucceed(tableSize, sizeof(ELLLIST *), "gphInitPvt");
pgphPvt->size = size;
pgphPvt->mask = size - 1;
pgphPvt->paplist = callocMustSucceed(size, sizeof(ELLLIST *), "gphInitPvt");
pgphPvt->lock = epicsMutexMustCreate();
*ppvt = (void *)pgphPvt;
*ppvt = pgphPvt;
return;
}
GPHENTRY * epicsShareAPI gphFind(void *pvt, const char *name, void *pvtid)
GPHENTRY * epicsShareAPI gphFind(gphPvt *pgphPvt, const char *name, void *pvtid)
{
int hashInd;
gphPvt *pgphPvt = (gphPvt *)pvt;
ELLLIST **paplist;
ELLLIST *gphlist;
GPHENTRY *pgphNode;
ELLLIST **paplist;
ELLLIST *gphlist;
GPHENTRY *pgphNode;
int hash;
if (pgphPvt == NULL) return NULL;
paplist = pgphPvt->paplist;
hashInd = hash(name, pgphPvt->nShift);
hash = epicsMemHash((char *)&pvtid, sizeof(void *), 0);
hash = epicsStrHash(name, hash) & pgphPvt->mask;
epicsMutexMustLock(pgphPvt->lock);
gphlist = paplist[hashInd];
gphlist = paplist[hash];
if (gphlist == NULL) {
pgphNode = NULL;
} else {
pgphNode = (GPHENTRY *) ellFirst(gphlist);
}
while (pgphNode) {
if (strcmp(name, pgphNode->name) == 0) {
if (pvtid == pgphNode->pvtid) break;
}
if (pvtid == pgphNode->pvtid &&
strcmp(name, pgphNode->name) == 0) break;
pgphNode = (GPHENTRY *) ellNext((ELLNODE *)pgphNode);
}
epicsMutexUnlock(pgphPvt->lock);
return pgphNode;
}
GPHENTRY * epicsShareAPI gphAdd(void *pvt,const char *name,void *pvtid)
GPHENTRY * epicsShareAPI gphAdd(gphPvt *pgphPvt, const char *name, void *pvtid)
{
int hashInd;
gphPvt *pgphPvt = (gphPvt *)pvt;
ELLLIST **paplist;
ELLLIST *plist;
GPHENTRY *pgphNode;
if (pgphPvt==NULL) return NULL;
ELLLIST **paplist;
ELLLIST *plist;
GPHENTRY *pgphNode;
int hash;
if (pgphPvt == NULL) return NULL;
paplist = pgphPvt->paplist;
hashInd = hash(name,pgphPvt->nShift);
hash = epicsMemHash((char *)&pvtid, sizeof(void *), 0);
hash = epicsStrHash(name, hash) & pgphPvt->mask;
epicsMutexMustLock(pgphPvt->lock);
plist = paplist[hashInd];
plist = paplist[hash];
if (plist == NULL) {
plist = callocMustSucceed(1, sizeof(ELLLIST), "gphAdd");
ellInit(plist);
paplist[hashInd] = plist;
paplist[hash] = plist;
}
pgphNode = (GPHENTRY *) ellFirst(plist);
while (pgphNode) {
if ((strcmp(name, pgphNode->name) == 0) &&
(pvtid == pgphNode->pvtid)) {
if (pvtid == pgphNode->pvtid &&
strcmp(name, pgphNode->name) == 0) {
epicsMutexUnlock(pgphPvt->lock);
return NULL;
}
pgphNode = (GPHENTRY *) ellNext((ELLNODE *)pgphNode);
}
pgphNode = callocMustSucceed(1, sizeof(GPHENTRY), "gphAdd");
pgphNode->name = name;
pgphNode->pvtid = pvtid;
ellAdd(plist, (ELLNODE *)pgphNode);
epicsMutexUnlock(pgphPvt->lock);
return (pgphNode);
}
void epicsShareAPI gphDelete(void *pvt,const char *name,void *pvtid)
void epicsShareAPI gphDelete(gphPvt *pgphPvt, const char *name, void *pvtid)
{
int hashInd;
gphPvt *pgphPvt = (gphPvt *)pvt;
ELLLIST **paplist;
ELLLIST *plist = NULL;
GPHENTRY *pgphNode;
if(pgphPvt==NULL) return;
ELLLIST **paplist;
ELLLIST *plist = NULL;
GPHENTRY *pgphNode;
int hash;
if (pgphPvt == NULL) return;
paplist = pgphPvt->paplist;
hashInd = hash(name,pgphPvt->nShift);
hash = epicsMemHash((char *)&pvtid, sizeof(void *), 0);
hash = epicsStrHash(name, hash) & pgphPvt->mask;
epicsMutexMustLock(pgphPvt->lock);
if(paplist[hashInd] == NULL) {
pgphNode = NULL;
if (paplist[hash] == NULL) {
pgphNode = NULL;
} else {
plist=paplist[hashInd];
pgphNode = (GPHENTRY *) ellFirst(plist);
plist = paplist[hash];
pgphNode = (GPHENTRY *) ellFirst(plist);
}
while(pgphNode) {
if((strcmp(name,(char *)pgphNode->name) == 0)
&&(pvtid == pgphNode->pvtid)) {
ellDelete(plist, (ELLNODE*)pgphNode);
free((void *)pgphNode);
break;
}
pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode);
if (pvtid == pgphNode->pvtid &&
strcmp(name, pgphNode->name) == 0) {
ellDelete(plist, (ELLNODE*)pgphNode);
free((void *)pgphNode);
break;
}
pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode);
}
epicsMutexUnlock(pgphPvt->lock);
return;
}
void epicsShareAPI gphFreeMem(void *pvt)
void epicsShareAPI gphFreeMem(gphPvt *pgphPvt)
{
int hashInd;
gphPvt *pgphPvt = (gphPvt *)pvt;
ELLLIST **paplist;
ELLLIST *plist;
GPHENTRY *pgphNode;
GPHENTRY *next;;
/*caller must ensure that no other thread is using *pvt */
if(pgphPvt==NULL) return;
ELLLIST **paplist;
int h;
/* Caller must ensure that no other thread is using *pvt */
if (pgphPvt == NULL) return;
paplist = pgphPvt->paplist;
for (hashInd=0; hashInd<pgphPvt->tableSize; hashInd++) {
if(paplist[hashInd] == NULL) continue;
plist=paplist[hashInd];
pgphNode = (GPHENTRY *) ellFirst(plist);
while(pgphNode) {
next = (GPHENTRY *) ellNext((ELLNODE*)pgphNode);
ellDelete(plist,(ELLNODE*)pgphNode);
free((void *)pgphNode);
pgphNode = next;
}
free((void *)paplist[hashInd]);
for (h = 0; h < pgphPvt->size; h++) {
ELLLIST *plist = paplist[h];
GPHENTRY *pgphNode;
GPHENTRY *next;
if (plist == NULL) continue;
pgphNode = (GPHENTRY *) ellFirst(plist);
while (pgphNode) {
next = (GPHENTRY *) ellNext((ELLNODE*)pgphNode);
ellDelete(plist, (ELLNODE*)pgphNode);
free(pgphNode);
pgphNode = next;
}
free(paplist[h]);
}
epicsMutexDestroy(pgphPvt->lock);
free((void *)paplist);
free((void *)pgphPvt);
free(paplist);
free(pgphPvt);
}
void epicsShareAPI gphDump(void *pvt)
void epicsShareAPI gphDump(gphPvt *pgphPvt)
{
gphDumpFP(stdout,pvt);
gphDumpFP(stdout, pgphPvt);
}
void epicsShareAPI gphDumpFP(FILE *fp,void *pvt)
void epicsShareAPI gphDumpFP(FILE *fp, gphPvt *pgphPvt)
{
int hashInd;
gphPvt *pgphPvt = (gphPvt *)pvt;
ELLLIST **paplist;
ELLLIST *plist;
GPHENTRY *pgphNode;
int number;
if(pgphPvt==NULL) return;
unsigned int empty = 0;
ELLLIST **paplist;
int h;
if (pgphPvt == NULL) return;
printf("Hash table has %d buckets", pgphPvt->size);
paplist = pgphPvt->paplist;
for (hashInd=0; hashInd<pgphPvt->tableSize; hashInd++) {
if(paplist[hashInd] == NULL) continue;
plist=paplist[hashInd];
pgphNode = (GPHENTRY *) ellFirst(plist);
fprintf(fp,"\n %3.3hd=%3.3d",hashInd,ellCount(plist));
number=0;
while(pgphNode) {
fprintf(fp," %s %p",pgphNode->name,pgphNode->pvtid);
if(number++ ==2) {number=0;fprintf(fp,"\n ");}
pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode);
}
for (h = 0; h < pgphPvt->size; h++) {
ELLLIST *plist = paplist[h];
GPHENTRY *pgphNode;
int i = 0;
if (plist == NULL) {
empty++;
continue;
}
pgphNode = (GPHENTRY *) ellFirst(plist);
fprintf(fp, "\n [%3d] %3d ", h, ellCount(plist));
while (pgphNode) {
if (!(++i % 3))
fprintf(fp, "\n ");
fprintf(fp, " %s %p", pgphNode->name, pgphNode->pvtid);
pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode);
}
}
fprintf(fp,"\n End of General Purpose Hash\n");
fprintf(fp, "\n%u buckets empty.\n", empty);
}