lset version and report
This commit is contained in:
@@ -709,6 +709,8 @@ static void scanLinkOnce(dbCommon *prec, caLink *pca) {
|
||||
}
|
||||
|
||||
static lset dbCa_lset = {
|
||||
LSET_API_VERSION,
|
||||
dbCaReportLink,
|
||||
dbCaRemoveLink,
|
||||
isConnected,
|
||||
getDBFtype, getElements,
|
||||
|
||||
@@ -49,6 +49,7 @@ extern struct ca_client_context * dbCaClientContext;
|
||||
|
||||
#ifdef EPICS_DBCA_PRIVATE_API
|
||||
epicsShareFunc void dbCaSync(void);
|
||||
void dbCaReportLink(const struct link *plink, dbLinkReportInfo *pinfo);
|
||||
#endif
|
||||
|
||||
/* These macros are for backwards compatibility */
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define EPICS_DBCA_PRIVATE_API
|
||||
#include "dbDefs.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsPrint.h"
|
||||
@@ -52,7 +53,60 @@
|
||||
#include "dbLock.h"
|
||||
#include "link.h"
|
||||
|
||||
|
||||
void dbCaReportLink(const struct link *plink, dbLinkReportInfo *pinfo)
|
||||
{
|
||||
caLink * const pca = (caLink *)plink->value.pv_link.pvt;
|
||||
const char * fname = dbGetFieldName(pinfo->pentry),
|
||||
* rname = dbGetRecordName(pinfo->pentry);
|
||||
|
||||
assert(pca);
|
||||
epicsMutexLock(pca->lock);
|
||||
assert(pca->plink==plink);
|
||||
|
||||
pinfo->connected = ca_field_type(pca->chid) != TYPENOTCONN;
|
||||
pinfo->nWriteFail = pca->nNoWrite;
|
||||
|
||||
if (pinfo->connected) {
|
||||
pinfo->readable = ca_read_access(pca->chid);
|
||||
pinfo->writable = ca_write_access(pca->chid);
|
||||
|
||||
if (pinfo->filter==dbLinkReportAll || pinfo->filter==dbLinkReportConnected) {
|
||||
int rw = pinfo->readable |
|
||||
pinfo->writable << 1;
|
||||
static const char *rights[4] = {
|
||||
"No Access", "Read Only",
|
||||
"Write Only", "Read/Write"
|
||||
};
|
||||
int mask = plink->value.pv_link.pvlMask;
|
||||
printf(LSET_REPORT_INDENT "%28s.%-4s ==> %-28s (%lu, %lu)\n",
|
||||
rname,
|
||||
fname,
|
||||
plink->value.pv_link.pvname,
|
||||
pca->nDisconnect,
|
||||
pca->nNoWrite);
|
||||
printf(LSET_REPORT_INDENT "%21s [%s%s%s%s] host %s, %s\n", "",
|
||||
mask & pvlOptInpNative ? "IN" : " ",
|
||||
mask & pvlOptInpString ? "IS" : " ",
|
||||
mask & pvlOptOutNative ? "ON" : " ",
|
||||
mask & pvlOptOutString ? "OS" : " ",
|
||||
ca_host_name(pca->chid),
|
||||
rights[rw]);
|
||||
}
|
||||
} else {
|
||||
if (pinfo->filter==dbLinkReportAll || pinfo->filter==dbLinkReportDisconnected) {
|
||||
printf("%28s.%-4s --> %-28s (%lu, %lu)\n",
|
||||
rname,
|
||||
fname,
|
||||
plink->value.pv_link.pvname,
|
||||
pca->nDisconnect,
|
||||
pca->nNoWrite);
|
||||
}
|
||||
}
|
||||
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
|
||||
|
||||
long dbcar(char *precordname, int level)
|
||||
{
|
||||
DBENTRY dbentry;
|
||||
@@ -68,7 +122,7 @@ long dbcar(char *precordname, int level)
|
||||
int noWriteAccess=0;
|
||||
unsigned long nDisconnect=0;
|
||||
unsigned long nNoWrite=0;
|
||||
caLink *pca;
|
||||
|
||||
int j;
|
||||
|
||||
if (!precordname || precordname[0] == '\0' || !strcmp(precordname, "*")) {
|
||||
@@ -90,50 +144,26 @@ long dbcar(char *precordname, int level)
|
||||
dbScanLock(precord);
|
||||
for (j=0; j<pdbRecordType->no_links; j++) {
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[j]];
|
||||
pdbentry->pflddes = pdbFldDes;
|
||||
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
|
||||
if (plink->type == CA_LINK) {
|
||||
ncalinks++;
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
if (pca
|
||||
&& pca->chid
|
||||
&& (ca_field_type(pca->chid) != TYPENOTCONN)) {
|
||||
nconnected++;
|
||||
nDisconnect += pca->nDisconnect;
|
||||
nNoWrite += pca->nNoWrite;
|
||||
if (!ca_read_access(pca->chid)) noReadAccess++;
|
||||
if (!ca_write_access(pca->chid)) noWriteAccess++;
|
||||
if (level>1) {
|
||||
int rw = ca_read_access(pca->chid) |
|
||||
ca_write_access(pca->chid) << 1;
|
||||
static const char *rights[4] = {
|
||||
"No Access", "Read Only",
|
||||
"Write Only", "Read/Write"
|
||||
};
|
||||
int mask = plink->value.pv_link.pvlMask;
|
||||
printf("%28s.%-4s ==> %-28s (%lu, %lu)\n",
|
||||
precord->name,
|
||||
pdbFldDes->name,
|
||||
plink->value.pv_link.pvname,
|
||||
pca->nDisconnect,
|
||||
pca->nNoWrite);
|
||||
printf("%21s [%s%s%s%s] host %s, %s\n", "",
|
||||
mask & pvlOptInpNative ? "IN" : " ",
|
||||
mask & pvlOptInpString ? "IS" : " ",
|
||||
mask & pvlOptOutNative ? "ON" : " ",
|
||||
mask & pvlOptOutString ? "OS" : " ",
|
||||
ca_host_name(pca->chid),
|
||||
rights[rw]);
|
||||
}
|
||||
} else {
|
||||
if (level>0) {
|
||||
printf("%28s.%-4s --> %-28s (%lu, %lu)\n",
|
||||
precord->name,
|
||||
pdbFldDes->name,
|
||||
plink->value.pv_link.pvname,
|
||||
pca->nDisconnect,
|
||||
pca->nNoWrite);
|
||||
}
|
||||
}
|
||||
dbLinkReportInfo linfo;
|
||||
memset(&linfo, 0, sizeof(linfo));
|
||||
linfo.pentry = pdbentry;
|
||||
if(level==0)
|
||||
linfo.filter = dbLinkReportNone;
|
||||
else if(level==1)
|
||||
linfo.filter = dbLinkReportDisconnected;
|
||||
else
|
||||
linfo.filter = dbLinkReportAll;
|
||||
if(level>2)
|
||||
linfo.detailLevel = level-2;
|
||||
dbReportLink(plink, &linfo);
|
||||
nconnected += linfo.connected;
|
||||
nDisconnect += !linfo.connected;
|
||||
noReadAccess += !linfo.readable;
|
||||
noWriteAccess += !linfo.writable;
|
||||
}
|
||||
}
|
||||
dbScanUnlock(precord);
|
||||
@@ -190,7 +220,7 @@ void dbcaStats(int *pchans, int *pdiscon)
|
||||
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
|
||||
if (plink->type == CA_LINK) {
|
||||
ncalinks++;
|
||||
if (dbCaIsLinkConnected(plink)) {
|
||||
if (dbIsLinkConnected(plink)) {
|
||||
nconnected++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +139,8 @@ static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
}
|
||||
|
||||
static lset dbConst_lset = {
|
||||
LSET_API_VERSION,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, dbConstGetNelements,
|
||||
@@ -431,6 +433,8 @@ static void dbDbScanFwdLink(struct link *plink)
|
||||
}
|
||||
|
||||
static lset dbDb_lset = {
|
||||
LSET_API_VERSION,
|
||||
NULL,
|
||||
dbDbRemoveLink,
|
||||
dbDbIsConnected,
|
||||
dbDbGetDBFtype, dbDbGetElements,
|
||||
@@ -446,6 +450,36 @@ static lset dbDb_lset = {
|
||||
|
||||
void (*dbAddLinkHook)(struct link *link, short dbfType);
|
||||
|
||||
/* initialize CA_LINK with possibly custom lset */
|
||||
static
|
||||
void customlset(struct link *plink, short dbfType)
|
||||
{
|
||||
int oops = 0;
|
||||
plink->lset = NULL;
|
||||
if(dbAddLinkHook)
|
||||
(*dbAddLinkHook)(plink, dbfType);
|
||||
|
||||
if((plink->lset==NULL) ^ (plink->type==PV_LINK)) {
|
||||
oops = 1;
|
||||
errlogPrintf("custom link types must set both type and lset.\n");
|
||||
}
|
||||
if(plink->lset && plink->lset->version!=LSET_API_VERSION) {
|
||||
oops = 1;
|
||||
errlogPrintf("custom link types must set .version to LSET_API_VERSION (%u) not %u\n",
|
||||
LSET_API_VERSION, plink->lset->version);
|
||||
}
|
||||
if(oops)
|
||||
{
|
||||
plink->lset = NULL;
|
||||
plink->type = PV_LINK;
|
||||
plink->value.pv_link.pvt = NULL; // leaking
|
||||
/* TODO, turn into CONSTANT? */
|
||||
}
|
||||
|
||||
if(!plink->lset)
|
||||
dbCaAddLink(NULL, plink, dbfType);
|
||||
}
|
||||
|
||||
void dbInitLink(struct link *plink, short dbfType)
|
||||
{
|
||||
struct dbCommon *precord = plink->precord;
|
||||
@@ -471,17 +505,7 @@ void dbInitLink(struct link *plink, short dbfType)
|
||||
if (dbfType == DBF_INLINK)
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
|
||||
plink->lset = NULL;
|
||||
if(dbAddLinkHook)
|
||||
(*dbAddLinkHook)(plink, dbfType);
|
||||
if((plink->lset==NULL) ^ (plink->type==PV_LINK)) {
|
||||
errlogPrintf("custom link types must set both type and lset.\n");
|
||||
plink->lset = NULL;
|
||||
plink->type = PV_LINK;
|
||||
plink->value.pv_link.pvt = NULL; // leaking
|
||||
}
|
||||
if(!plink->lset)
|
||||
dbCaAddLink(NULL, plink, dbfType);
|
||||
customlset(plink, dbfType);
|
||||
if (dbfType == DBF_FWDLINK) {
|
||||
char *pperiod = strrchr(plink->value.pv_link.pvname, '.');
|
||||
|
||||
@@ -520,11 +544,7 @@ void dbAddLink(dbLocker *locker, struct link *plink, short dbfType, DBADDR *ptar
|
||||
if (dbfType == DBF_INLINK)
|
||||
plink->value.pv_link.pvlMask |= pvlOptInpNative;
|
||||
|
||||
plink->lset = NULL;
|
||||
if(dbAddLinkHook)
|
||||
(*dbAddLinkHook)(plink, dbfType);
|
||||
if(!plink->lset)
|
||||
dbCaAddLink(locker, plink, dbfType);
|
||||
customlset(plink, dbfType);
|
||||
if (dbfType == DBF_FWDLINK) {
|
||||
char *pperiod = strrchr(plink->value.pv_link.pvname, '.');
|
||||
|
||||
@@ -553,6 +573,15 @@ void dbRemoveLink(dbLocker *locker, struct link *plink)
|
||||
}
|
||||
}
|
||||
|
||||
void dbReportLink(const struct link *plink, dbLinkReportInfo *pinfo)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
if (plset && plset->reportLink) {
|
||||
plset->reportLink(plink, pinfo);
|
||||
}
|
||||
}
|
||||
|
||||
int dbIsLinkConnected(const struct link *plink)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
@@ -26,8 +26,36 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct dbLocker;
|
||||
struct DBENTRY;
|
||||
|
||||
#define LSET_API_VERSION 1
|
||||
#define LSET_REPORT_INDENT ""
|
||||
|
||||
typedef enum {
|
||||
dbLinkReportNone,
|
||||
dbLinkReportAll,
|
||||
dbLinkReportConnected,
|
||||
dbLinkReportDisconnected,
|
||||
} dbLinkReportFilter;
|
||||
|
||||
typedef struct {
|
||||
/* from caller */
|
||||
dbLinkReportFilter filter;
|
||||
int detailLevel;
|
||||
struct DBENTRY *pentry;
|
||||
unsigned clearstats:1; /* after reporting, zero stat counters */
|
||||
/* callee fills in current state */
|
||||
unsigned connected:1; /* is this link connected to it's underlying data source */
|
||||
unsigned readable:1; /* would a dbGetLink() succeed at this moment */
|
||||
unsigned writable:1; /* would a dbPutLink() succeed at this moment */
|
||||
/* callee fills in statistics */
|
||||
unsigned nEvents; /* number of times new data has been received from the underlying data source */
|
||||
unsigned nWriteFail; /* number of times dbPutLink() has failed for this link */
|
||||
} dbLinkReportInfo;
|
||||
|
||||
typedef struct lset {
|
||||
unsigned version; /* must be set to LSET_API_VERSION */
|
||||
void (*reportLink)(const struct link *plink, dbLinkReportInfo *pinfo);
|
||||
void (*removeLink)(struct dbLocker *locker, struct link *plink);
|
||||
int (*isConnected)(const struct link *plink);
|
||||
int (*getDBFtype)(const struct link *plink);
|
||||
@@ -58,6 +86,8 @@ epicsShareFunc long dbLoadLink(struct link *plink, short dbrType,
|
||||
void *pbuffer);
|
||||
epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink);
|
||||
|
||||
epicsShareFunc void dbReportLink(const struct link *plink, dbLinkReportInfo *pinfo);
|
||||
|
||||
epicsShareFunc long dbGetNelements(const struct link *plink, long *nelements);
|
||||
epicsShareFunc int dbIsLinkConnected(const struct link *plink);
|
||||
epicsShareFunc int dbGetLinkDBFtype(const struct link *plink);
|
||||
|
||||
@@ -47,7 +47,7 @@ extern "C" {
|
||||
|
||||
typedef dbBase DBBASE;
|
||||
|
||||
typedef struct{
|
||||
typedef struct DBENTRY {
|
||||
DBBASE *pdbbase;
|
||||
dbRecordType *precordType;
|
||||
dbFldDes *pflddes;
|
||||
|
||||
Reference in New Issue
Block a user