long dbcar(char *precordname, int level) { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; long status; dbCommon *precord; dbRecordType *pdbRecordType; dbFldDes *pdbFldDes; DBLINK *plink; int ncalinks=0; int nconnected=0; int noReadAccess=0; int noWriteAccess=0; unsigned long nDisconnect=0; unsigned long nNoWrite=0; caLink *pca; int j; if (!precordname || precordname[0] == '\0' || !strcmp(precordname, "*")) { precordname = NULL; printf("CA links in all records\n\n"); } else { printf("CA links in record named '%s'\n\n", precordname); } dbInitEntry(pdbbase,pdbentry); status = dbFirstRecordType(pdbentry); while (!status) { status = dbFirstRecord(pdbentry); while (!status) { if (precordname ? !strcmp(precordname, dbGetRecordName(pdbentry)) : !dbIsAlias(pdbentry)) { pdbRecordType = pdbentry->precordType; precord = (dbCommon *)pdbentry->precnode->precord; for (j=0; j<pdbRecordType->no_links; j++) { pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[j]]; plink = (DBLINK *)((char *)precord + pdbFldDes->offset); dbLockSetGblLock(); 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); } } } dbLockSetGblUnlock(); } if (precordname) goto done; } status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } done: if ((level > 1 && nconnected > 0) || (level > 0 && ncalinks != nconnected)) printf("\n"); printf("Total %d CA link%s; ", ncalinks, (ncalinks != 1) ? "s" : ""); printf("%d connected, %d not connected.\n", nconnected, (ncalinks - nconnected)); printf(" %d can't read, %d can't write.", noReadAccess, noWriteAccess); printf(" (%lu disconnects, %lu writes prohibited)\n\n", nDisconnect, nNoWrite); dbFinishEntry(pdbentry); if ( level > 2 && dbCaClientContext != 0 ) { ca_context_status ( dbCaClientContext, level - 2 ); } return(0); }
static long dbPutFieldLink(DBADDR *paddr, short dbrType, const void *pbuffer, long nRequest) { dbCommon *precord = paddr->precord; dbFldDes *pfldDes = paddr->pfldDes; long special = paddr->special; DBLINK *plink = (DBLINK *)paddr->pfield; const char *pstring = (const char *)pbuffer; DBENTRY dbEntry; DBADDR dbaddr; struct dsxt *old_dsxt = NULL; struct dset *new_dset = NULL; struct dsxt *new_dsxt = NULL; long status; int isDevLink; short scan; switch (dbrType) { case DBR_CHAR: case DBR_UCHAR: if (pstring[nRequest - 1] != '\0') return S_db_badDbrtype; break; case DBR_STRING: break; default: return S_db_badDbrtype; } dbInitEntry(pdbbase, &dbEntry); status = dbFindRecord(&dbEntry, precord->name); if (!status) status = dbFindField(&dbEntry, pfldDes->name); if (status) goto finish; isDevLink = ellCount(&precord->rdes->devList) > 0 && (strcmp(pfldDes->name, "INP") == 0 || strcmp(pfldDes->name, "OUT") == 0); dbLockSetGblLock(); dbLockSetRecordLock(precord); scan = precord->scan; if (isDevLink) { devSup *pdevSup = dbDTYPtoDevSup(precord->rdes, precord->dtyp); if (pdevSup) { new_dset = pdevSup->pdset; new_dsxt = pdevSup->pdsxt; } if (precord->dset) { pdevSup = dbDSETtoDevSup(precord->rdes, precord->dset); if (pdevSup) old_dsxt = pdevSup->pdsxt; } if (new_dsxt == NULL || new_dsxt->add_record == NULL || (precord->dset && old_dsxt == NULL) || (old_dsxt && old_dsxt->del_record == NULL)) { status = S_db_noSupport; goto unlock; } if (scan == menuScanI_O_Intr) { scanDelete(precord); precord->scan = menuScanPassive; } if (old_dsxt) { status = old_dsxt->del_record(precord); if (status) goto restoreScan; } } switch (plink->type) { /* Old link type */ case DB_LINK: free(plink->value.pv_link.pvt); plink->value.pv_link.pvt = 0; plink->type = PV_LINK; plink->value.pv_link.getCvt = 0; plink->value.pv_link.pvlMask = 0; plink->value.pv_link.lastGetdbrType = 0; dbLockSetSplit(precord); break; case CA_LINK: dbCaRemoveLink(plink); plink->type = PV_LINK; plink->value.pv_link.getCvt = 0; plink->value.pv_link.pvlMask = 0; plink->value.pv_link.lastGetdbrType = 0; break; case CONSTANT: break; /* do nothing */ case PV_LINK: case MACRO_LINK: break; /* should never get here */ default: /* Hardware address */ if (!isDevLink) { status = S_db_badHWaddr; goto restoreScan; } break; } if (special) status = dbPutSpecial(paddr, 0); if (!status) status = dbPutString(&dbEntry, pstring); if (!status && special) status = dbPutSpecial(paddr, 1); if (status) { if (isDevLink) { precord->dset = NULL; precord->pact = TRUE; } goto postScanEvent; } if (isDevLink) { precord->dpvt = NULL; precord->dset = new_dset; precord->pact = FALSE; status = new_dsxt->add_record(precord); if (status) { precord->dset = NULL; precord->pact = TRUE; goto postScanEvent; } } switch (plink->type) { /* New link type */ case PV_LINK: if (plink == &precord->tsel) recGblTSELwasModified(plink); plink->value.pv_link.precord = precord; if (!(plink->value.pv_link.pvlMask & (pvlOptCA|pvlOptCP|pvlOptCPP)) && (dbNameToAddr(plink->value.pv_link.pvname, &dbaddr) == 0)) { /* It's a DB link */ DBADDR *pdbAddr; plink->type = DB_LINK; pdbAddr = dbMalloc(sizeof(struct dbAddr)); *pdbAddr = dbaddr; /* NB: structure copy */; plink->value.pv_link.pvt = pdbAddr; dbLockSetRecordLock(pdbAddr->precord); dbLockSetMerge(precord, pdbAddr->precord); } else { /* Make it a CA link */ char *pperiod; plink->type = CA_LINK; if (pfldDes->field_type == DBF_INLINK) { plink->value.pv_link.pvlMask |= pvlOptInpNative; } dbCaAddLink(plink); if (pfldDes->field_type == DBF_FWDLINK) { pperiod = strrchr(plink->value.pv_link.pvname, '.'); if (pperiod && strstr(pperiod, "PROC")) plink->value.pv_link.pvlMask |= pvlOptFWD; } } break; case CONSTANT: break; case DB_LINK: case CA_LINK: case MACRO_LINK: break; /* should never get here */ default: /* Hardware address */ if (!isDevLink) { status = S_db_badHWaddr; goto postScanEvent; } break; } db_post_events(precord, plink, DBE_VALUE | DBE_LOG); restoreScan: if (isDevLink && scan == menuScanI_O_Intr) { /* undo scanDelete() */ precord->scan = scan; scanAdd(precord); } postScanEvent: if (scan != precord->scan) db_post_events(precord, &precord->scan, DBE_VALUE|DBE_LOG); unlock: dbLockSetGblUnlock(); finish: dbFinishEntry(&dbEntry); return status; }