Files
epics-base/src/dbStatic/dbPvdLib.c
2009-04-09 17:28:59 +00:00

228 lines
6.0 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*************************************************************************\
* 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 is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbPvdLib.c */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.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"
typedef struct {
ELLLIST list;
epicsMutexId lock;
} dbPvdBucket;
typedef struct dbPvd {
unsigned int size;
unsigned int mask;
dbPvdBucket **buckets;
} dbPvd;
unsigned int dbPvdHashTableSize = 0;
#define MIN_SIZE 256
#define DEFAULT_SIZE 512
#define MAX_SIZE 65536
int dbPvdTableSize(int size)
{
if (size & (size - 1)) {
printf("dbPvdTableSize: %d is not a power of 2\n", size);
return -1;
}
if (size < MIN_SIZE)
size = MIN_SIZE;
if (size > MAX_SIZE)
size = MAX_SIZE;
dbPvdHashTableSize = size;
return 0;
}
void dbPvdInitPvt(dbBase *pdbbase)
{
dbPvd *ppvd;
if (pdbbase->ppvd) return;
if (dbPvdHashTableSize == 0) {
dbPvdHashTableSize = DEFAULT_SIZE;
}
ppvd = (dbPvd *)dbMalloc(sizeof(dbPvd));
ppvd->size = dbPvdHashTableSize;
ppvd->mask = dbPvdHashTableSize - 1;
ppvd->buckets = dbCalloc(ppvd->size, sizeof(dbPvdBucket *));
pdbbase->ppvd = ppvd;
return;
}
PVDENTRY *dbPvdFind(dbBase *pdbbase, const char *name, int lenName)
{
dbPvd *ppvd = pdbbase->ppvd;
dbPvdBucket *pbucket;
PVDENTRY *ppvdNode;
pbucket = ppvd->buckets[epicsMemHash(name, lenName, 0) & ppvd->mask];
if (pbucket == NULL) return NULL;
epicsMutexMustLock(pbucket->lock);
ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
while (ppvdNode) {
const char *recordname = ppvdNode->precnode->recordname;
if (strncmp(name, recordname, lenName) == 0 &&
strlen(recordname) == lenName)
break;
ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode);
}
epicsMutexUnlock(pbucket->lock);
return ppvdNode;
}
PVDENTRY *dbPvdAdd(dbBase *pdbbase, dbRecordType *precordType,
dbRecordNode *precnode)
{
dbPvd *ppvd = pdbbase->ppvd;
dbPvdBucket *pbucket;
PVDENTRY *ppvdNode;
char *name = precnode->recordname;
unsigned int h;
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;
}
epicsMutexMustLock(pbucket->lock);
ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list);
while (ppvdNode) {
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(&pbucket->list, (ELLNODE *)ppvdNode);
epicsMutexUnlock(pbucket->lock);
return ppvdNode;
}
void dbPvdDelete(dbBase *pdbbase, dbRecordNode *precnode)
{
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)
{
dbPvd *ppvd = pdbbase->ppvd;
unsigned int h;
if (ppvd == NULL) return;
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)
{
unsigned int empty = 0;
dbPvd *ppvd;
unsigned int h;
if (!pdbbase) {
fprintf(stderr,"pdbbase not specified\n");
return;
}
ppvd = pdbbase->ppvd;
if (ppvd == NULL) return;
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("\n%u buckets empty.\n", empty);
}