Merged changes from 3.14 branch into 3.15
This commit is contained in:
@@ -95,11 +95,12 @@ CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
|
||||
# Compiler flags for C++ files
|
||||
|
||||
#
|
||||
# -W<N> use warning level N
|
||||
# (maximum lint level warnings at level 4)
|
||||
# -w44355 set "'this' used in the base initializer list" to be level 4
|
||||
# -W<n> disable warnings from levels > n
|
||||
# -w<n><m> set warning m to level n
|
||||
# -w44355 "'this' used in the base initializer list"
|
||||
# -w44344 "behavior change: use of explicit template arguments results in ..."
|
||||
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344
|
||||
# -w44251 "class needs to have dll-interface to be used by clients of ..."
|
||||
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251
|
||||
WARN_CXXFLAGS_NO = -W1
|
||||
|
||||
#
|
||||
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
|
||||
<h2 align="center">Changes from the 3.14 branch since 3.15.5</h2>
|
||||
|
||||
<!-- Insert inherited items immediately below here ... -->
|
||||
|
||||
<h3>Fix DNS related crash on exit</h3>
|
||||
|
||||
<p>The attempt to fix DNS related delays for short lived CLI programs (eg. caget)
|
||||
in lp:1527636 introduced a bug which cased these short lived clients to crash on exit.
|
||||
This bug should now be fixed.</p>
|
||||
|
||||
<h3>Server bind issue on Windows</h3>
|
||||
|
||||
<p>When a National Instruments network variables CA server is already running on
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
* 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
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
%{
|
||||
static int yyerror(char *);
|
||||
@@ -29,9 +28,7 @@ static ASGRULE *yyAsgRule=NULL;
|
||||
%union
|
||||
{
|
||||
int Int;
|
||||
char Char;
|
||||
char *Str;
|
||||
double Real;
|
||||
}
|
||||
|
||||
%%
|
||||
@@ -208,11 +205,12 @@ rule_hag_list_name: tokenSTRING
|
||||
|
||||
static int yyerror(char *str)
|
||||
{
|
||||
if (strlen(str)) epicsPrintf("%s\n", str);
|
||||
epicsPrintf("Access Security file error at line %d\n",
|
||||
line_num);
|
||||
if (strlen(str))
|
||||
errlogPrintf("%s at line %d\n", str, line_num);
|
||||
else
|
||||
errlogPrintf("Error at line %d\n", line_num);
|
||||
yyFailed = TRUE;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
static int myParse(ASINPUTFUNCPTR inputfunction)
|
||||
{
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/* share/src/as/asLibRoutines.c */
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, 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
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* Author: Marty Kraimer Date: 10-15-93 */
|
||||
|
||||
@@ -22,7 +20,7 @@
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "errlog.h"
|
||||
#include "gpHash.h"
|
||||
#include "freeList.h"
|
||||
#include "macLib.h"
|
||||
@@ -109,7 +107,7 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
|
||||
pasg = (ASG *)ellFirst(&pasbasenew->asgList);
|
||||
while(pasg) {
|
||||
pasg->pavalue = asCalloc(CALCPERFORM_NARGS, sizeof(double));
|
||||
pasg = (ASG *)ellNext((ELLNODE *)pasg);
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
}
|
||||
gphInitPvt(&pasbasenew->phash, 256);
|
||||
/*Hash each uagname and each hagname*/
|
||||
@@ -119,12 +117,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
|
||||
while(puagname) {
|
||||
pgphentry = gphAdd(pasbasenew->phash,puagname->user,puag);
|
||||
if(!pgphentry) {
|
||||
epicsPrintf("Duplicated user '%s' in UAG '%s'\n",
|
||||
errlogPrintf("Duplicated user '%s' in UAG '%s'\n",
|
||||
puagname->user, puag->name);
|
||||
}
|
||||
puagname = (UAGNAME *)ellNext((ELLNODE *)puagname);
|
||||
puagname = (UAGNAME *)ellNext(&puagname->node);
|
||||
}
|
||||
puag = (UAG *)ellNext((ELLNODE *)puag);
|
||||
puag = (UAG *)ellNext(&puag->node);
|
||||
}
|
||||
phag = (HAG *)ellFirst(&pasbasenew->hagList);
|
||||
while(phag) {
|
||||
@@ -132,12 +130,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
|
||||
while(phagname) {
|
||||
pgphentry = gphAdd(pasbasenew->phash,phagname->host,phag);
|
||||
if(!pgphentry) {
|
||||
epicsPrintf("Duplicated host '%s' in HAG '%s'\n",
|
||||
errlogPrintf("Duplicated host '%s' in HAG '%s'\n",
|
||||
phagname->host, phag->name);
|
||||
}
|
||||
phagname = (HAGNAME *)ellNext((ELLNODE *)phagname);
|
||||
phagname = (HAGNAME *)ellNext(&phagname->node);
|
||||
}
|
||||
phag = (HAG *)ellNext((ELLNODE *)phag);
|
||||
phag = (HAG *)ellNext(&phag->node);
|
||||
}
|
||||
pasbaseold = (ASBASE *)pasbase;
|
||||
pasbase = (ASBASE volatile *)pasbasenew;
|
||||
@@ -150,12 +148,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
|
||||
while(poldasg) {
|
||||
poldmem = (ASGMEMBER *)ellFirst(&poldasg->memberList);
|
||||
while(poldmem) {
|
||||
pnextoldmem = (ASGMEMBER *)ellNext((ELLNODE *)poldmem);
|
||||
ellDelete(&poldasg->memberList,(ELLNODE *)poldmem);
|
||||
pnextoldmem = (ASGMEMBER *)ellNext(&poldmem->node);
|
||||
ellDelete(&poldasg->memberList,&poldmem->node);
|
||||
status = asAddMemberPvt(&poldmem,poldmem->asgName);
|
||||
poldmem = pnextoldmem;
|
||||
}
|
||||
poldasg = (ASG *)ellNext((ELLNODE *)poldasg);
|
||||
poldasg = (ASG *)ellNext(&poldasg->node);
|
||||
}
|
||||
asFreeAll(pasbaseold);
|
||||
}
|
||||
@@ -201,7 +199,7 @@ static int myInputFunction(char *buf, int max_size)
|
||||
n = macExpandString(macHandle,mac_input_buffer,
|
||||
my_buffer,BUF_SIZE);
|
||||
if(n<0) {
|
||||
epicsPrintf("access security: macExpandString failed\n"
|
||||
errlogPrintf("access security: macExpandString failed\n"
|
||||
"input line: %s\n",mac_input_buffer);
|
||||
return(0);
|
||||
}
|
||||
@@ -241,7 +239,7 @@ long epicsShareAPI asInitFP(FILE *fp,const char *substitutions)
|
||||
macHandle = NULL;
|
||||
} else {
|
||||
macInstallMacros(macHandle,macPairs);
|
||||
free((void *)macPairs);
|
||||
free(macPairs);
|
||||
mac_input_buffer = mac_buffer;
|
||||
}
|
||||
}
|
||||
@@ -277,13 +275,13 @@ long epicsShareAPI asRemoveMember(ASMEMBERPVT *asMemberPvt)
|
||||
return(S_asLib_clientsExist);
|
||||
}
|
||||
if(pasgmember->pasg) {
|
||||
ellDelete(&pasgmember->pasg->memberList,(ELLNODE *)pasgmember);
|
||||
ellDelete(&pasgmember->pasg->memberList,&pasgmember->node);
|
||||
} else {
|
||||
errMessage(-1,"Logic error in asRemoveMember");
|
||||
UNLOCK;
|
||||
return(-1);
|
||||
}
|
||||
free((void *)pasgmember);
|
||||
free(pasgmember);
|
||||
*asMemberPvt = NULL;
|
||||
UNLOCK;
|
||||
return(0);
|
||||
@@ -299,7 +297,7 @@ long epicsShareAPI asChangeGroup(ASMEMBERPVT *asMemberPvt,const char *newAsgName
|
||||
if(!pasgmember) return(S_asLib_badMember);
|
||||
LOCK;
|
||||
if(pasgmember->pasg) {
|
||||
ellDelete(&pasgmember->pasg->memberList,(ELLNODE *)pasgmember);
|
||||
ellDelete(&pasgmember->pasg->memberList,&pasgmember->node);
|
||||
} else {
|
||||
errMessage(-1,"Logic error in asChangeGroup");
|
||||
UNLOCK;
|
||||
@@ -351,7 +349,7 @@ long epicsShareAPI asAddClient(ASCLIENTPVT *pasClientPvt,ASMEMBERPVT asMemberPvt
|
||||
pasgclient->user = user;
|
||||
pasgclient->host = host;
|
||||
LOCK;
|
||||
ellAdd(&pasgmember->clientList,(ELLNODE *)pasgclient);
|
||||
ellAdd(&pasgmember->clientList,&pasgclient->node);
|
||||
status = asComputePvt(pasgclient);
|
||||
UNLOCK;
|
||||
return(status);
|
||||
@@ -393,7 +391,7 @@ long epicsShareAPI asRemoveClient(ASCLIENTPVT *asClientPvt)
|
||||
UNLOCK;
|
||||
return(-1);
|
||||
}
|
||||
ellDelete(&pasgMember->clientList,(ELLNODE *)pasgclient);
|
||||
ellDelete(&pasgMember->clientList,&pasgclient->node);
|
||||
UNLOCK;
|
||||
freeListFree(freeListPvt,pasgclient);
|
||||
*asClientPvt = NULL;
|
||||
@@ -506,10 +504,10 @@ int epicsShareAPI asDumpFP(
|
||||
if(puagname) fprintf(fp," {"); else fprintf(fp,"\n");
|
||||
while(puagname) {
|
||||
fprintf(fp,"%s",puagname->user);
|
||||
puagname = (UAGNAME *)ellNext((ELLNODE *)puagname);
|
||||
puagname = (UAGNAME *)ellNext(&puagname->node);
|
||||
if(puagname) fprintf(fp,","); else fprintf(fp,"}\n");
|
||||
}
|
||||
puag = (UAG *)ellNext((ELLNODE *)puag);
|
||||
puag = (UAG *)ellNext(&puag->node);
|
||||
}
|
||||
phag = (HAG *)ellFirst(&pasbase->hagList);
|
||||
if(!phag) fprintf(fp,"No HAGs\n");
|
||||
@@ -519,10 +517,10 @@ int epicsShareAPI asDumpFP(
|
||||
if(phagname) fprintf(fp," {"); else fprintf(fp,"\n");
|
||||
while(phagname) {
|
||||
fprintf(fp,"%s",phagname->host);
|
||||
phagname = (HAGNAME *)ellNext((ELLNODE *)phagname);
|
||||
phagname = (HAGNAME *)ellNext(&phagname->node);
|
||||
if(phagname) fprintf(fp,","); else fprintf(fp,"}\n");
|
||||
}
|
||||
phag = (HAG *)ellNext((ELLNODE *)phag);
|
||||
phag = (HAG *)ellNext(&phag->node);
|
||||
}
|
||||
pasg = (ASG *)ellFirst(&pasbase->asgList);
|
||||
if(!pasg) fprintf(fp,"No ASGs\n");
|
||||
@@ -550,7 +548,7 @@ int epicsShareAPI asDumpFP(
|
||||
fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]);
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp);
|
||||
pasginp = (ASGINP *)ellNext(&pasginp->node);
|
||||
}
|
||||
while(pasgrule) {
|
||||
int print_end_brace;
|
||||
@@ -570,14 +568,14 @@ int epicsShareAPI asDumpFP(
|
||||
if(pasguag) fprintf(fp,"\t\tUAG(");
|
||||
while(pasguag) {
|
||||
fprintf(fp,"%s",pasguag->puag->name);
|
||||
pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag);
|
||||
pasguag = (ASGUAG *)ellNext(&pasguag->node);
|
||||
if(pasguag) fprintf(fp,","); else fprintf(fp,")\n");
|
||||
}
|
||||
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
|
||||
if(pasghag) fprintf(fp,"\t\tHAG(");
|
||||
while(pasghag) {
|
||||
fprintf(fp,"%s",pasghag->phag->name);
|
||||
pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag);
|
||||
pasghag = (ASGHAG *)ellNext(&pasghag->node);
|
||||
if(pasghag) fprintf(fp,","); else fprintf(fp,")\n");
|
||||
}
|
||||
if(pasgrule->calc) {
|
||||
@@ -587,7 +585,7 @@ int epicsShareAPI asDumpFP(
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
if(print_end_brace) fprintf(fp,"\t}\n");
|
||||
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
|
||||
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
|
||||
}
|
||||
pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
|
||||
if(!verbose) pasgmember = NULL;
|
||||
@@ -614,12 +612,12 @@ int epicsShareAPI asDumpFP(
|
||||
fprintf(fp," Illegal Access %d",pasgclient->access);
|
||||
if(clientcallback) clientcallback(pasgclient,fp);
|
||||
fprintf(fp,"\n");
|
||||
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
|
||||
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
|
||||
}
|
||||
pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember);
|
||||
pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
|
||||
}
|
||||
if(print_end_brace) fprintf(fp,"}\n");
|
||||
pasg = (ASG *)ellNext((ELLNODE *)pasg);
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -639,7 +637,7 @@ int epicsShareAPI asDumpUagFP(FILE *fp,const char *uagname)
|
||||
if(!puag) fprintf(fp,"No UAGs\n");
|
||||
while(puag) {
|
||||
if(uagname && strcmp(uagname,puag->name)!=0) {
|
||||
puag = (UAG *)ellNext((ELLNODE *)puag);
|
||||
puag = (UAG *)ellNext(&puag->node);
|
||||
continue;
|
||||
}
|
||||
fprintf(fp,"UAG(%s)",puag->name);
|
||||
@@ -647,10 +645,10 @@ int epicsShareAPI asDumpUagFP(FILE *fp,const char *uagname)
|
||||
if(puagname) fprintf(fp," {"); else fprintf(fp,"\n");
|
||||
while(puagname) {
|
||||
fprintf(fp,"%s",puagname->user);
|
||||
puagname = (UAGNAME *)ellNext((ELLNODE *)puagname);
|
||||
puagname = (UAGNAME *)ellNext(&puagname->node);
|
||||
if(puagname) fprintf(fp,","); else fprintf(fp,"}\n");
|
||||
}
|
||||
puag = (UAG *)ellNext((ELLNODE *)puag);
|
||||
puag = (UAG *)ellNext(&puag->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -670,7 +668,7 @@ int epicsShareAPI asDumpHagFP(FILE *fp,const char *hagname)
|
||||
if(!phag) fprintf(fp,"No HAGs\n");
|
||||
while(phag) {
|
||||
if(hagname && strcmp(hagname,phag->name)!=0) {
|
||||
phag = (HAG *)ellNext((ELLNODE *)phag);
|
||||
phag = (HAG *)ellNext(&phag->node);
|
||||
continue;
|
||||
}
|
||||
fprintf(fp,"HAG(%s)",phag->name);
|
||||
@@ -678,10 +676,10 @@ int epicsShareAPI asDumpHagFP(FILE *fp,const char *hagname)
|
||||
if(phagname) fprintf(fp," {"); else fprintf(fp,"\n");
|
||||
while(phagname) {
|
||||
fprintf(fp,"%s",phagname->host);
|
||||
phagname = (HAGNAME *)ellNext((ELLNODE *)phagname);
|
||||
phagname = (HAGNAME *)ellNext(&phagname->node);
|
||||
if(phagname) fprintf(fp,","); else fprintf(fp,"}\n");
|
||||
}
|
||||
phag = (HAG *)ellNext((ELLNODE *)phag);
|
||||
phag = (HAG *)ellNext(&phag->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -706,7 +704,7 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
int print_end_brace;
|
||||
|
||||
if(asgname && strcmp(asgname,pasg->name)!=0) {
|
||||
pasg = (ASG *)ellNext((ELLNODE *)pasg);
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
continue;
|
||||
}
|
||||
fprintf(fp,"ASG(%s)",pasg->name);
|
||||
@@ -726,7 +724,7 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
fprintf(fp," INVALID");
|
||||
fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]);
|
||||
fprintf(fp,"\n");
|
||||
pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp);
|
||||
pasginp = (ASGINP *)ellNext(&pasginp->node);
|
||||
}
|
||||
while(pasgrule) {
|
||||
int print_end_brace;
|
||||
@@ -746,14 +744,14 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
if(pasguag) fprintf(fp,"\t\tUAG(");
|
||||
while(pasguag) {
|
||||
fprintf(fp,"%s",pasguag->puag->name);
|
||||
pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag);
|
||||
pasguag = (ASGUAG *)ellNext(&pasguag->node);
|
||||
if(pasguag) fprintf(fp,","); else fprintf(fp,")\n");
|
||||
}
|
||||
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
|
||||
if(pasghag) fprintf(fp,"\t\tHAG(");
|
||||
while(pasghag) {
|
||||
fprintf(fp,"%s",pasghag->phag->name);
|
||||
pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag);
|
||||
pasghag = (ASGHAG *)ellNext(&pasghag->node);
|
||||
if(pasghag) fprintf(fp,","); else fprintf(fp,")\n");
|
||||
}
|
||||
if(pasgrule->calc) {
|
||||
@@ -762,10 +760,10 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
if(print_end_brace) fprintf(fp,"\t}\n");
|
||||
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
|
||||
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
|
||||
}
|
||||
if(print_end_brace) fprintf(fp,"}\n");
|
||||
pasg = (ASG *)ellNext((ELLNODE *)pasg);
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -789,7 +787,7 @@ int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname,
|
||||
while(pasg) {
|
||||
|
||||
if(asgname && strcmp(asgname,pasg->name)!=0) {
|
||||
pasg = (ASG *)ellNext((ELLNODE *)pasg);
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
continue;
|
||||
}
|
||||
fprintf(fp,"ASG(%s)\n",pasg->name);
|
||||
@@ -818,11 +816,11 @@ int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname,
|
||||
else
|
||||
fprintf(fp," Illegal Access %d",pasgclient->access);
|
||||
fprintf(fp,"\n");
|
||||
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
|
||||
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
|
||||
}
|
||||
pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember);
|
||||
pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
|
||||
}
|
||||
pasg = (ASG *)ellNext((ELLNODE *)pasg);
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -873,23 +871,23 @@ static long asAddMemberPvt(ASMEMBERPVT *pasMemberPvt,const char *asgName)
|
||||
pgroup = (ASG *)ellFirst(&pasbase->asgList);
|
||||
while(pgroup) {
|
||||
if(strcmp(pgroup->name,pasgmember->asgName)==0) goto got_it;
|
||||
pgroup = (ASG *)ellNext((ELLNODE *)pgroup);
|
||||
pgroup = (ASG *)ellNext(&pgroup->node);
|
||||
}
|
||||
/* Put it in DEFAULT*/
|
||||
pgroup = (ASG *)ellFirst(&pasbase->asgList);
|
||||
while(pgroup) {
|
||||
if(strcmp(pgroup->name,DEFAULT)==0) goto got_it;
|
||||
pgroup = (ASG *)ellNext((ELLNODE *)pgroup);
|
||||
pgroup = (ASG *)ellNext(&pgroup->node);
|
||||
}
|
||||
errMessage(-1,"Logic Error in asAddMember");
|
||||
return(-1);
|
||||
got_it:
|
||||
pasgmember->pasg = pgroup;
|
||||
ellAdd(&pgroup->memberList,(ELLNODE *)pasgmember);
|
||||
ellAdd(&pgroup->memberList,&pasgmember->node);
|
||||
pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
|
||||
while(pasgclient) {
|
||||
asComputePvt((ASCLIENTPVT)pasgclient);
|
||||
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
|
||||
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -902,7 +900,7 @@ static long asComputeAllAsgPvt(void)
|
||||
pasg = (ASG *)ellFirst(&pasbase->asgList);
|
||||
while(pasg) {
|
||||
asComputeAsgPvt(pasg);
|
||||
pasg = (ASG *)ellNext((ELLNODE *)pasg);
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -928,7 +926,7 @@ static long asComputeAsgPvt(ASG *pasg)
|
||||
pasgrule->result = ((result>.99) && (result<1.01)) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
|
||||
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
|
||||
}
|
||||
pasg->inpChanged = FALSE;
|
||||
pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
|
||||
@@ -936,9 +934,9 @@ static long asComputeAsgPvt(ASG *pasg)
|
||||
pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
|
||||
while(pasgclient) {
|
||||
asComputePvt((ASCLIENTPVT)pasgclient);
|
||||
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
|
||||
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
|
||||
}
|
||||
pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember);
|
||||
pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -977,7 +975,7 @@ static long asComputePvt(ASCLIENTPVT asClientPvt)
|
||||
pgphentry = gphFind(pasbase->phash,pasgclient->user,puag);
|
||||
if(pgphentry) goto check_hag;
|
||||
}
|
||||
pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag);
|
||||
pasguag = (ASGUAG *)ellNext(&pasguag->node);
|
||||
}
|
||||
goto next_rule;
|
||||
}
|
||||
@@ -993,7 +991,7 @@ check_hag:
|
||||
pgphentry=gphFind(pasbase->phash,pasgclient->host,phag);
|
||||
if(pgphentry) goto check_calc;
|
||||
}
|
||||
pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag);
|
||||
pasghag = (ASGHAG *)ellNext(&pasghag->node);
|
||||
}
|
||||
goto next_rule;
|
||||
}
|
||||
@@ -1004,7 +1002,7 @@ check_calc:
|
||||
trapMask = pasgrule->trapMask;
|
||||
}
|
||||
next_rule:
|
||||
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
|
||||
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
|
||||
}
|
||||
pasgclient->access = access;
|
||||
pasgclient->trapMask = trapMask;
|
||||
@@ -1031,70 +1029,70 @@ void asFreeAll(ASBASE *pasbase)
|
||||
while(puag) {
|
||||
puagname = (UAGNAME *)ellFirst(&puag->list);
|
||||
while(puagname) {
|
||||
pnext = ellNext((ELLNODE *)puagname);
|
||||
ellDelete(&puag->list,(ELLNODE *)puagname);
|
||||
free((void *)puagname);
|
||||
pnext = ellNext(&puagname->node);
|
||||
ellDelete(&puag->list,&puagname->node);
|
||||
free(puagname);
|
||||
puagname = pnext;
|
||||
}
|
||||
pnext = ellNext((ELLNODE *)puag);
|
||||
ellDelete(&pasbase->uagList,(ELLNODE *)puag);
|
||||
free((void *)puag);
|
||||
pnext = ellNext(&puag->node);
|
||||
ellDelete(&pasbase->uagList,&puag->node);
|
||||
free(puag);
|
||||
puag = pnext;
|
||||
}
|
||||
phag = (HAG *)ellFirst(&pasbase->hagList);
|
||||
while(phag) {
|
||||
phagname = (HAGNAME *)ellFirst(&phag->list);
|
||||
while(phagname) {
|
||||
pnext = ellNext((ELLNODE *)phagname);
|
||||
ellDelete(&phag->list,(ELLNODE *)phagname);
|
||||
free((void *)phagname);
|
||||
pnext = ellNext(&phagname->node);
|
||||
ellDelete(&phag->list,&phagname->node);
|
||||
free(phagname);
|
||||
phagname = pnext;
|
||||
}
|
||||
pnext = ellNext((ELLNODE *)phag);
|
||||
ellDelete(&pasbase->hagList,(ELLNODE *)phag);
|
||||
free((void *)phag);
|
||||
pnext = ellNext(&phag->node);
|
||||
ellDelete(&pasbase->hagList,&phag->node);
|
||||
free(phag);
|
||||
phag = pnext;
|
||||
}
|
||||
pasg = (ASG *)ellFirst(&pasbase->asgList);
|
||||
while(pasg) {
|
||||
free((void *)pasg->pavalue);
|
||||
free(pasg->pavalue);
|
||||
pasginp = (ASGINP *)ellFirst(&pasg->inpList);
|
||||
while(pasginp) {
|
||||
pnext = ellNext((ELLNODE *)pasginp);
|
||||
ellDelete(&pasg->inpList,(ELLNODE *)pasginp);
|
||||
free((void *)pasginp);
|
||||
pnext = ellNext(&pasginp->node);
|
||||
ellDelete(&pasg->inpList,&pasginp->node);
|
||||
free(pasginp);
|
||||
pasginp = pnext;
|
||||
}
|
||||
pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
|
||||
while(pasgrule) {
|
||||
free((void *)pasgrule->calc);
|
||||
free((void *)pasgrule->rpcl);
|
||||
free(pasgrule->calc);
|
||||
free(pasgrule->rpcl);
|
||||
pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
|
||||
while(pasguag) {
|
||||
pnext = ellNext((ELLNODE *)pasguag);
|
||||
ellDelete(&pasgrule->uagList,(ELLNODE *)pasguag);
|
||||
free((void *)pasguag);
|
||||
pnext = ellNext(&pasguag->node);
|
||||
ellDelete(&pasgrule->uagList,&pasguag->node);
|
||||
free(pasguag);
|
||||
pasguag = pnext;
|
||||
}
|
||||
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
|
||||
while(pasghag) {
|
||||
pnext = ellNext((ELLNODE *)pasghag);
|
||||
ellDelete(&pasgrule->hagList,(ELLNODE *)pasghag);
|
||||
free((void *)pasghag);
|
||||
pnext = ellNext(&pasghag->node);
|
||||
ellDelete(&pasgrule->hagList,&pasghag->node);
|
||||
free(pasghag);
|
||||
pasghag = pnext;
|
||||
}
|
||||
pnext = ellNext((ELLNODE *)pasgrule);
|
||||
ellDelete(&pasg->ruleList,(ELLNODE *)pasgrule);
|
||||
free((void *)pasgrule);
|
||||
pnext = ellNext(&pasgrule->node);
|
||||
ellDelete(&pasg->ruleList,&pasgrule->node);
|
||||
free(pasgrule);
|
||||
pasgrule = pnext;
|
||||
}
|
||||
pnext = ellNext((ELLNODE *)pasg);
|
||||
ellDelete(&pasbase->asgList,(ELLNODE *)pasg);
|
||||
free((void *)pasg);
|
||||
pnext = ellNext(&pasg->node);
|
||||
ellDelete(&pasbase->asgList,&pasg->node);
|
||||
free(pasg);
|
||||
pasg = pnext;
|
||||
}
|
||||
gphFreeMem(pasbase->phash);
|
||||
free((void *)pasbase);
|
||||
free(pasbase);
|
||||
}
|
||||
|
||||
/*Beginning of routines called by lex code*/
|
||||
@@ -1115,17 +1113,17 @@ static UAG *asUagAdd(const char *uagName)
|
||||
errlogPrintf("Duplicate User Access Group named '%s'\n", uagName);
|
||||
return(NULL);
|
||||
}
|
||||
pnext = (UAG *)ellNext((ELLNODE *)pnext);
|
||||
pnext = (UAG *)ellNext(&pnext->node);
|
||||
}
|
||||
puag = asCalloc(1,sizeof(UAG)+strlen(uagName)+1);
|
||||
ellInit(&puag->list);
|
||||
puag->name = (char *)(puag+1);
|
||||
strcpy(puag->name,uagName);
|
||||
if(pnext==NULL) { /*Add to end of list*/
|
||||
ellAdd(&pasbase->uagList,(ELLNODE *)puag);
|
||||
ellAdd(&pasbase->uagList,&puag->node);
|
||||
} else {
|
||||
pprev = (UAG *)ellPrevious((ELLNODE *)pnext);
|
||||
ellInsert(&pasbase->uagList,(ELLNODE *)pprev,(ELLNODE *)puag);
|
||||
pprev = (UAG *)ellPrevious(&pnext->node);
|
||||
ellInsert(&pasbase->uagList,&pprev->node,&puag->node);
|
||||
}
|
||||
return(puag);
|
||||
}
|
||||
@@ -1138,7 +1136,7 @@ static long asUagAddUser(UAG *puag,const char *user)
|
||||
puagname = asCalloc(1,sizeof(UAGNAME)+strlen(user)+1);
|
||||
puagname->user = (char *)(puagname+1);
|
||||
strcpy(puagname->user,user);
|
||||
ellAdd(&puag->list,(ELLNODE *)puagname);
|
||||
ellAdd(&puag->list,&puagname->node);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1159,17 +1157,17 @@ static HAG *asHagAdd(const char *hagName)
|
||||
errlogPrintf("Duplicate Host Access Group named '%s'\n", hagName);
|
||||
return(NULL);
|
||||
}
|
||||
pnext = (HAG *)ellNext((ELLNODE *)pnext);
|
||||
pnext = (HAG *)ellNext(&pnext->node);
|
||||
}
|
||||
phag = asCalloc(1,sizeof(HAG)+strlen(hagName)+1);
|
||||
ellInit(&phag->list);
|
||||
phag->name = (char *)(phag+1);
|
||||
strcpy(phag->name,hagName);
|
||||
if(pnext==NULL) { /*Add to end of list*/
|
||||
ellAdd(&pasbase->hagList,(ELLNODE *)phag);
|
||||
ellAdd(&pasbase->hagList,&phag->node);
|
||||
} else {
|
||||
pprev = (HAG *)ellPrevious((ELLNODE *)pnext);
|
||||
ellInsert(&pasbase->hagList,(ELLNODE *)pprev,(ELLNODE *)phag);
|
||||
pprev = (HAG *)ellPrevious(&pnext->node);
|
||||
ellInsert(&pasbase->hagList,&pprev->node,&phag->node);
|
||||
}
|
||||
return(phag);
|
||||
}
|
||||
@@ -1186,7 +1184,7 @@ static long asHagAddHost(HAG *phag,const char *host)
|
||||
for (i = 0; i < len; i++) {
|
||||
phagname->host[i] = (char)tolower((int)host[i]);
|
||||
}
|
||||
ellAdd(&phag->list, (ELLNODE *)phagname);
|
||||
ellAdd(&phag->list, &phagname->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1212,7 +1210,7 @@ static ASG *asAsgAdd(const char *asgName)
|
||||
errlogPrintf("Duplicate Access Security Group named '%s'\n", asgName);
|
||||
return(NULL);
|
||||
}
|
||||
pnext = (ASG *)ellNext((ELLNODE *)pnext);
|
||||
pnext = (ASG *)ellNext(&pnext->node);
|
||||
}
|
||||
pasg = asCalloc(1,sizeof(ASG)+strlen(asgName)+1);
|
||||
ellInit(&pasg->inpList);
|
||||
@@ -1221,10 +1219,10 @@ static ASG *asAsgAdd(const char *asgName)
|
||||
pasg->name = (char *)(pasg+1);
|
||||
strcpy(pasg->name,asgName);
|
||||
if(pnext==NULL) { /*Add to end of list*/
|
||||
ellAdd(&pasbase->asgList,(ELLNODE *)pasg);
|
||||
ellAdd(&pasbase->asgList,&pasg->node);
|
||||
} else {
|
||||
pprev = (ASG *)ellPrevious((ELLNODE *)pnext);
|
||||
ellInsert(&pasbase->asgList,(ELLNODE *)pprev,(ELLNODE *)pasg);
|
||||
pprev = (ASG *)ellPrevious(&pnext->node);
|
||||
ellInsert(&pasbase->asgList,&pprev->node,&pasg->node);
|
||||
}
|
||||
return(pasg);
|
||||
}
|
||||
@@ -1239,7 +1237,7 @@ static long asAsgAddInp(ASG *pasg,const char *inp,int inpIndex)
|
||||
strcpy(pasginp->inp,inp);
|
||||
pasginp->pasg = pasg;
|
||||
pasginp->inpIndex = inpIndex;
|
||||
ellAdd(&pasg->inpList,(ELLNODE *)pasginp);
|
||||
ellAdd(&pasg->inpList,&pasginp->node);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1254,7 +1252,7 @@ static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level)
|
||||
pasgrule->level = level;
|
||||
ellInit(&pasgrule->uagList);
|
||||
ellInit(&pasgrule->hagList);
|
||||
ellAdd(&pasg->ruleList,(ELLNODE *)pasgrule);
|
||||
ellAdd(&pasg->ruleList,&pasgrule->node);
|
||||
return(pasgrule);
|
||||
}
|
||||
|
||||
@@ -1265,48 +1263,56 @@ static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long asAsgRuleUagAdd(ASGRULE *pasgrule,const char *name)
|
||||
static long asAsgRuleUagAdd(ASGRULE *pasgrule, const char *name)
|
||||
{
|
||||
ASGUAG *pasguag;
|
||||
UAG *puag;
|
||||
ASBASE *pasbase = (ASBASE *)pasbasenew;
|
||||
|
||||
if(!pasgrule) return(0);
|
||||
if (!pasgrule)
|
||||
return 0;
|
||||
|
||||
puag = (UAG *)ellFirst(&pasbase->uagList);
|
||||
while(puag) {
|
||||
if(strcmp(puag->name,name)==0) break;
|
||||
puag = (UAG *)ellNext((ELLNODE *)puag);
|
||||
while (puag) {
|
||||
if (strcmp(puag->name, name)==0)
|
||||
break;
|
||||
puag = (UAG *)ellNext(&puag->node);
|
||||
}
|
||||
if(!puag){
|
||||
errlogPrintf("No User Access Group named '%s' defined\n", name);
|
||||
return(S_asLib_noUag);
|
||||
if (!puag){
|
||||
errlogPrintf("No User Access Group named '%s' defined\n", name);
|
||||
return S_asLib_noUag;
|
||||
}
|
||||
pasguag = asCalloc(1,sizeof(ASGUAG));
|
||||
|
||||
pasguag = asCalloc(1, sizeof(ASGUAG));
|
||||
pasguag->puag = puag;
|
||||
ellAdd(&pasgrule->uagList,(ELLNODE *)pasguag);
|
||||
return(0);
|
||||
ellAdd(&pasgrule->uagList, &pasguag->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long asAsgRuleHagAdd(ASGRULE *pasgrule,const char *name)
|
||||
static long asAsgRuleHagAdd(ASGRULE *pasgrule, const char *name)
|
||||
{
|
||||
ASGHAG *pasghag;
|
||||
HAG *phag;
|
||||
ASBASE *pasbase = (ASBASE *)pasbasenew;
|
||||
|
||||
if(!pasgrule) return(0);
|
||||
if (!pasgrule)
|
||||
return 0;
|
||||
|
||||
phag = (HAG *)ellFirst(&pasbase->hagList);
|
||||
while(phag) {
|
||||
if(strcmp(phag->name,name)==0) break;
|
||||
phag = (HAG *)ellNext((ELLNODE *)phag);
|
||||
while (phag) {
|
||||
if (strcmp(phag->name, name)==0)
|
||||
break;
|
||||
phag = (HAG *)ellNext(&phag->node);
|
||||
}
|
||||
if(!phag){
|
||||
errlogPrintf("No Host Access Group named '%s' defined\n", name);
|
||||
return(S_asLib_noHag);
|
||||
if (!phag){
|
||||
errlogPrintf("No Host Access Group named '%s' defined\n", name);
|
||||
return S_asLib_noHag;
|
||||
}
|
||||
pasghag = asCalloc(1,sizeof(ASGHAG));
|
||||
|
||||
pasghag = asCalloc(1, sizeof(ASGHAG));
|
||||
pasghag->phag = phag;
|
||||
ellAdd(&pasgrule->hagList,(ELLNODE *)pasghag);
|
||||
return(0);
|
||||
ellAdd(&pasgrule->hagList, &pasghag->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
|
||||
@@ -1323,8 +1329,8 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
|
||||
pasgrule->rpcl = asCalloc(1, INFIX_TO_POSTFIX_SIZE(insize));
|
||||
status = postfix(pasgrule->calc, pasgrule->rpcl, &err);
|
||||
if(status) {
|
||||
free((void *)pasgrule->calc);
|
||||
free((void *)pasgrule->rpcl);
|
||||
free(pasgrule->calc);
|
||||
free(pasgrule->rpcl);
|
||||
pasgrule->calc = NULL;
|
||||
pasgrule->rpcl = NULL;
|
||||
status = S_asLib_badCalc;
|
||||
@@ -1334,8 +1340,8 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
|
||||
calcArgUsage(pasgrule->rpcl, &pasgrule->inpUsed, &stores);
|
||||
/* Until someone proves stores are not dangerous, don't allow them */
|
||||
if (stores) {
|
||||
free((void *)pasgrule->calc);
|
||||
free((void *)pasgrule->rpcl);
|
||||
free(pasgrule->calc);
|
||||
free(pasgrule->rpcl);
|
||||
pasgrule->calc = NULL;
|
||||
pasgrule->rpcl = NULL;
|
||||
status = S_asLib_badCalc;
|
||||
|
||||
@@ -3,18 +3,21 @@
|
||||
* 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
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
digit [0-9]
|
||||
name [a-zA-Z0-9_\-:\.\[\]<>;]
|
||||
notquote [^\"]
|
||||
escapequote \\\"
|
||||
string {notquote}|{escapequote}
|
||||
newline "\n"
|
||||
backslash "\\"
|
||||
doublequote "\""
|
||||
comment "#"
|
||||
whitespace [ \t\r]
|
||||
escape {backslash}.
|
||||
stringchar [^"\n\\]
|
||||
|
||||
name [a-zA-Z0-9_\-+:.\[\]<>;]
|
||||
digit [0-9]
|
||||
punctuation [(){},]
|
||||
link [A-L]
|
||||
link [A-L]
|
||||
|
||||
%{
|
||||
static ASINPUTFUNCPTR *my_yyinput;
|
||||
@@ -37,46 +40,55 @@ HAG { return(tokenHAG); }
|
||||
ASG { return(tokenASG); }
|
||||
RULE { return(tokenRULE); }
|
||||
CALC { return(tokenCALC); }
|
||||
|
||||
INP{link} {
|
||||
yylval.Int = (unsigned char)yytext[3];
|
||||
yylval.Int -= 'A';
|
||||
return(tokenINP);
|
||||
}
|
||||
}
|
||||
|
||||
{digit}+ { /*integer*/
|
||||
yylval.Int = atoi((char *)yytext);
|
||||
return(tokenINTEGER);
|
||||
}
|
||||
}
|
||||
|
||||
{name}+ { /*unquoted string*/
|
||||
yylval.Str=asStrdup(yytext);
|
||||
return(tokenSTRING);
|
||||
}
|
||||
}
|
||||
|
||||
\"{string}*\" { /*quoted string*/
|
||||
/* making sure that neither double quote gets passed back */
|
||||
{doublequote}({stringchar}|{escape})*{doublequote} { /* quoted string */
|
||||
yylval.Str=asStrdup(yytext+1);
|
||||
yylval.Str[strlen(yylval.Str)-1] = '\0';
|
||||
return(tokenSTRING);
|
||||
}
|
||||
}
|
||||
|
||||
{doublequote}({stringchar}|{escape})*{newline} { /* bad string */
|
||||
yyerror("Newline in quoted string, closing quote missing");
|
||||
}
|
||||
|
||||
{punctuation} { return(yytext[0]); }
|
||||
|
||||
^#.*
|
||||
{whitespace} ;
|
||||
{newline} { line_num++; }
|
||||
|
||||
\n { line_num ++;}
|
||||
{comment}.* ;
|
||||
{whitespace} ;
|
||||
|
||||
. {
|
||||
char message[40];
|
||||
YY_BUFFER_STATE *dummy=0;
|
||||
|
||||
sprintf(message,"invalid character '%c'",yytext[0]);
|
||||
if (isprint((int) yytext[0])) {
|
||||
sprintf(message, "Invalid character '%c'", yytext[0]);
|
||||
}
|
||||
else {
|
||||
sprintf(message, "Invalid character 0x%2.2x", yytext[0]);
|
||||
}
|
||||
yyerror(message);
|
||||
|
||||
/*The following suppress compiler warning messages*/
|
||||
if (0) yyunput('c',(unsigned char *) message);
|
||||
if (0) yy_switch_to_buffer(*dummy);
|
||||
}
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
@@ -867,9 +867,9 @@ static void refer ( MAC_HANDLE *handle, MAC_ENTRY *entry, int level,
|
||||
if ( !refentry->visited ) {
|
||||
/* reference is good, use it */
|
||||
if ( !handle->dirty ) {
|
||||
/* copy the already-expanded value, and its error status! */
|
||||
/* copy the already-expanded value, merge any error status */
|
||||
cpy2val( refentry->value, &v, valend );
|
||||
entry->error = refentry->error;
|
||||
entry->error = entry->error || refentry->error;
|
||||
} else {
|
||||
/* translate raw value */
|
||||
const char *rv = refentry->rawval;
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include <stdexcept>
|
||||
#include <cstdio>
|
||||
|
||||
//#define EPICS_FREELIST_DEBUG
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "ipAddrToAsciiAsynchronous.h"
|
||||
#include "epicsThread.h"
|
||||
@@ -45,7 +48,6 @@ public:
|
||||
< ipAddrToAsciiTransactionPrivate, 0x80 > & );
|
||||
epicsPlacementDeleteOperator (( void *, tsFreeList
|
||||
< ipAddrToAsciiTransactionPrivate, 0x80 > & ))
|
||||
private:
|
||||
osiSockAddr addr;
|
||||
ipAddrToAsciiEnginePrivate & engine;
|
||||
ipAddrToAsciiCallBack * pCB;
|
||||
@@ -53,7 +55,7 @@ private:
|
||||
void ipAddrToAscii ( const osiSockAddr &, ipAddrToAsciiCallBack & );
|
||||
void release ();
|
||||
void operator delete ( void * );
|
||||
friend class ipAddrToAsciiEnginePrivate;
|
||||
private:
|
||||
ipAddrToAsciiTransactionPrivate & operator = ( const ipAddrToAsciiTransactionPrivate & );
|
||||
ipAddrToAsciiTransactionPrivate ( const ipAddrToAsciiTransactionPrivate & );
|
||||
};
|
||||
@@ -74,41 +76,54 @@ extern "C" {
|
||||
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
|
||||
}
|
||||
|
||||
// - this class executes the synchronous DNS query
|
||||
// - it creates one thread
|
||||
class ipAddrToAsciiEnginePrivate :
|
||||
public ipAddrToAsciiEngine,
|
||||
public epicsThreadRunable {
|
||||
public:
|
||||
ipAddrToAsciiEnginePrivate ();
|
||||
virtual ~ipAddrToAsciiEnginePrivate ();
|
||||
void show ( unsigned level ) const;
|
||||
private:
|
||||
namespace {
|
||||
struct ipAddrToAsciiGlobal : public epicsThreadRunable {
|
||||
ipAddrToAsciiGlobal();
|
||||
virtual ~ipAddrToAsciiGlobal() {}
|
||||
|
||||
virtual void run ();
|
||||
|
||||
char nameTmp [1024];
|
||||
tsFreeList
|
||||
< ipAddrToAsciiTransactionPrivate, 0x80 >
|
||||
tsFreeList
|
||||
< ipAddrToAsciiTransactionPrivate, 0x80 >
|
||||
transactionFreeList;
|
||||
tsDLList < ipAddrToAsciiTransactionPrivate > labor;
|
||||
mutable epicsMutex mutex;
|
||||
epicsEvent laborEvent;
|
||||
epicsEvent destructorBlockEvent;
|
||||
epicsThread thread;
|
||||
// pCurrent may be changed by any thread (worker or other)
|
||||
ipAddrToAsciiTransactionPrivate * pCurrent;
|
||||
// pActive may only be changed by the worker
|
||||
ipAddrToAsciiTransactionPrivate * pActive;
|
||||
unsigned cancelPendingCount;
|
||||
bool exitFlag;
|
||||
bool callbackInProgress;
|
||||
static ipAddrToAsciiEnginePrivate * pEngine;
|
||||
};
|
||||
}
|
||||
|
||||
// - this class executes the synchronous DNS query
|
||||
// - it creates one thread
|
||||
class ipAddrToAsciiEnginePrivate :
|
||||
public ipAddrToAsciiEngine {
|
||||
public:
|
||||
ipAddrToAsciiEnginePrivate() :refcount(1u), released(false) {}
|
||||
virtual ~ipAddrToAsciiEnginePrivate () {}
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
unsigned refcount;
|
||||
bool released;
|
||||
|
||||
static ipAddrToAsciiGlobal * pEngine;
|
||||
ipAddrToAsciiTransaction & createTransaction ();
|
||||
void release ();
|
||||
void run ();
|
||||
ipAddrToAsciiEnginePrivate ( const ipAddrToAsciiEngine & );
|
||||
void release ();
|
||||
|
||||
private:
|
||||
ipAddrToAsciiEnginePrivate ( const ipAddrToAsciiEngine & );
|
||||
ipAddrToAsciiEnginePrivate & operator = ( const ipAddrToAsciiEngine & );
|
||||
friend class ipAddrToAsciiEngine;
|
||||
friend class ipAddrToAsciiTransactionPrivate;
|
||||
friend void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
|
||||
};
|
||||
|
||||
ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
|
||||
ipAddrToAsciiGlobal * ipAddrToAsciiEnginePrivate :: pEngine = 0;
|
||||
static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
// the users are not required to supply a show routine
|
||||
@@ -123,12 +138,24 @@ ipAddrToAsciiEngine::~ipAddrToAsciiEngine () {}
|
||||
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * )
|
||||
{
|
||||
try {
|
||||
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiEnginePrivate ();
|
||||
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiGlobal ();
|
||||
} catch (std::exception& e) {
|
||||
errlogPrintf("ipAddrToAsciiEnginePrivate ctor fails with: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void ipAddrToAsciiEngine::cleanup()
|
||||
{
|
||||
{
|
||||
epicsGuard<epicsMutex> G(ipAddrToAsciiEnginePrivate::pEngine->mutex);
|
||||
ipAddrToAsciiEnginePrivate::pEngine->exitFlag = true;
|
||||
}
|
||||
ipAddrToAsciiEnginePrivate::pEngine->laborEvent.signal();
|
||||
ipAddrToAsciiEnginePrivate::pEngine->thread.exitWait();
|
||||
delete ipAddrToAsciiEnginePrivate::pEngine;
|
||||
ipAddrToAsciiEnginePrivate::pEngine = 0;
|
||||
}
|
||||
|
||||
// for now its probably sufficent to allocate one
|
||||
// DNS transaction thread for all codes sharing
|
||||
// the same process that need DNS services but we
|
||||
@@ -140,41 +167,78 @@ ipAddrToAsciiEngine & ipAddrToAsciiEngine::allocate ()
|
||||
ipAddrToAsciiEngineGlobalMutexConstruct, 0 );
|
||||
if(!ipAddrToAsciiEnginePrivate::pEngine)
|
||||
throw std::runtime_error("ipAddrToAsciiEngine::allocate fails");
|
||||
return * ipAddrToAsciiEnginePrivate::pEngine;
|
||||
return * new ipAddrToAsciiEnginePrivate();
|
||||
}
|
||||
|
||||
ipAddrToAsciiEnginePrivate::ipAddrToAsciiEnginePrivate () :
|
||||
ipAddrToAsciiGlobal::ipAddrToAsciiGlobal () :
|
||||
thread ( *this, "ipToAsciiProxy",
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
epicsThreadPriorityLow ),
|
||||
pCurrent ( 0 ), cancelPendingCount ( 0u ), exitFlag ( false ),
|
||||
pCurrent ( 0 ), pActive ( 0 ), cancelPendingCount ( 0u ), exitFlag ( false ),
|
||||
callbackInProgress ( false )
|
||||
{
|
||||
this->thread.start (); // start the thread
|
||||
}
|
||||
|
||||
ipAddrToAsciiEnginePrivate::~ipAddrToAsciiEnginePrivate ()
|
||||
{
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->exitFlag = true;
|
||||
}
|
||||
this->laborEvent.signal ();
|
||||
this->thread.exitWait ();
|
||||
}
|
||||
|
||||
void ipAddrToAsciiEnginePrivate::release ()
|
||||
{
|
||||
bool last;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->pEngine->mutex );
|
||||
if(released)
|
||||
throw std::logic_error("Engine release() called again!");
|
||||
|
||||
// released==true prevents new transactions
|
||||
released = true;
|
||||
|
||||
{
|
||||
// cancel any pending transactions
|
||||
tsDLIter < ipAddrToAsciiTransactionPrivate > it(pEngine->labor.firstIter());
|
||||
while(it.valid()) {
|
||||
ipAddrToAsciiTransactionPrivate *trn = it.pointer();
|
||||
++it;
|
||||
|
||||
if(this==&trn->engine) {
|
||||
trn->pending = false;
|
||||
pEngine->labor.remove(*trn);
|
||||
}
|
||||
}
|
||||
|
||||
// cancel transaction in lookup or callback
|
||||
if (pEngine->pCurrent && this==&pEngine->pCurrent->engine) {
|
||||
pEngine->pCurrent->pending = false;
|
||||
pEngine->pCurrent = 0;
|
||||
}
|
||||
|
||||
// wait for completion of in-progress callback
|
||||
pEngine->cancelPendingCount++;
|
||||
while(pEngine->pActive && this==&pEngine->pActive->engine
|
||||
&& ! pEngine->thread.isCurrentThread()) {
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
pEngine->destructorBlockEvent.wait();
|
||||
}
|
||||
pEngine->cancelPendingCount--;
|
||||
if(pEngine->cancelPendingCount)
|
||||
pEngine->destructorBlockEvent.signal();
|
||||
}
|
||||
|
||||
assert(refcount>0);
|
||||
last = 0==--refcount;
|
||||
}
|
||||
if(last) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->pEngine->mutex );
|
||||
printf ( "ipAddrToAsciiEngine at %p with %u requests pending\n",
|
||||
static_cast <const void *> (this), this->labor.count () );
|
||||
static_cast <const void *> (this), this->pEngine->labor.count () );
|
||||
if ( level > 0u ) {
|
||||
tsDLIterConst < ipAddrToAsciiTransactionPrivate >
|
||||
pItem = this->labor.firstIter ();
|
||||
tsDLIter < ipAddrToAsciiTransactionPrivate >
|
||||
pItem = this->pEngine->labor.firstIter ();
|
||||
while ( pItem.valid () ) {
|
||||
pItem->show ( level - 1u );
|
||||
pItem++;
|
||||
@@ -182,10 +246,10 @@ void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const
|
||||
}
|
||||
if ( level > 1u ) {
|
||||
printf ( "mutex:\n" );
|
||||
this->mutex.show ( level - 2u );
|
||||
this->pEngine->mutex.show ( level - 2u );
|
||||
printf ( "laborEvent:\n" );
|
||||
this->laborEvent.show ( level - 2u );
|
||||
printf ( "exitFlag boolean = %u\n", this->exitFlag );
|
||||
this->pEngine->laborEvent.show ( level - 2u );
|
||||
printf ( "exitFlag boolean = %u\n", this->pEngine->exitFlag );
|
||||
printf ( "exit event:\n" );
|
||||
}
|
||||
}
|
||||
@@ -218,10 +282,20 @@ void ipAddrToAsciiTransactionPrivate::operator delete ( void * )
|
||||
|
||||
ipAddrToAsciiTransaction & ipAddrToAsciiEnginePrivate::createTransaction ()
|
||||
{
|
||||
return * new ( this->transactionFreeList ) ipAddrToAsciiTransactionPrivate ( *this );
|
||||
epicsGuard <epicsMutex> G(this->pEngine->mutex);
|
||||
if(this->released)
|
||||
throw std::logic_error("createTransaction() on release()'d ipAddrToAsciiEngine");
|
||||
|
||||
assert(this->refcount>0);
|
||||
|
||||
ipAddrToAsciiTransactionPrivate *ret = new ( this->pEngine->transactionFreeList ) ipAddrToAsciiTransactionPrivate ( *this );
|
||||
|
||||
this->refcount++;
|
||||
|
||||
return * ret;
|
||||
}
|
||||
|
||||
void ipAddrToAsciiEnginePrivate::run ()
|
||||
void ipAddrToAsciiGlobal::run ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
while ( ! this->exitFlag ) {
|
||||
@@ -259,7 +333,7 @@ void ipAddrToAsciiEnginePrivate::run ()
|
||||
// fix for lp:1580623
|
||||
// a destructing cac sets pCurrent to NULL, so
|
||||
// make local copy to avoid race when releasing the guard
|
||||
ipAddrToAsciiTransactionPrivate *pCur = this->pCurrent;
|
||||
ipAddrToAsciiTransactionPrivate *pCur = pActive = pCurrent;
|
||||
this->callbackInProgress = true;
|
||||
|
||||
{
|
||||
@@ -269,6 +343,7 @@ void ipAddrToAsciiEnginePrivate::run ()
|
||||
}
|
||||
|
||||
this->callbackInProgress = false;
|
||||
pActive = 0;
|
||||
|
||||
if ( this->pCurrent ) {
|
||||
this->pCurrent->pending = false;
|
||||
@@ -292,44 +367,53 @@ ipAddrToAsciiTransactionPrivate::ipAddrToAsciiTransactionPrivate
|
||||
void ipAddrToAsciiTransactionPrivate::release ()
|
||||
{
|
||||
this->~ipAddrToAsciiTransactionPrivate ();
|
||||
this->engine.transactionFreeList.release ( this );
|
||||
this->engine.pEngine->transactionFreeList.release ( this );
|
||||
}
|
||||
|
||||
ipAddrToAsciiTransactionPrivate::~ipAddrToAsciiTransactionPrivate ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->engine.mutex );
|
||||
while ( this->pending ) {
|
||||
if ( this->engine.pCurrent == this &&
|
||||
this->engine.callbackInProgress &&
|
||||
! this->engine.thread.isCurrentThread() ) {
|
||||
// cancel from another thread while callback in progress
|
||||
// waits for callback to complete
|
||||
assert ( this->engine.cancelPendingCount < UINT_MAX );
|
||||
this->engine.cancelPendingCount++;
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
this->engine.destructorBlockEvent.wait ();
|
||||
}
|
||||
assert ( this->engine.cancelPendingCount > 0u );
|
||||
this->engine.cancelPendingCount--;
|
||||
if ( ! this->pending ) {
|
||||
if ( this->engine.cancelPendingCount ) {
|
||||
this->engine.destructorBlockEvent.signal ();
|
||||
ipAddrToAsciiGlobal *pGlobal = this->engine.pEngine;
|
||||
bool last;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pGlobal->mutex );
|
||||
while ( this->pending ) {
|
||||
if ( pGlobal->pCurrent == this &&
|
||||
pGlobal->callbackInProgress &&
|
||||
! pGlobal->thread.isCurrentThread() ) {
|
||||
// cancel from another thread while callback in progress
|
||||
// waits for callback to complete
|
||||
assert ( pGlobal->cancelPendingCount < UINT_MAX );
|
||||
pGlobal->cancelPendingCount++;
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
pGlobal->destructorBlockEvent.wait ();
|
||||
}
|
||||
assert ( pGlobal->cancelPendingCount > 0u );
|
||||
pGlobal->cancelPendingCount--;
|
||||
if ( ! this->pending ) {
|
||||
if ( pGlobal->cancelPendingCount ) {
|
||||
pGlobal->destructorBlockEvent.signal ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( this->engine.pCurrent == this ) {
|
||||
// cancel from callback, or while lookup in progress
|
||||
this->engine.pCurrent = 0;
|
||||
}
|
||||
else {
|
||||
// cancel before lookup starts
|
||||
this->engine.labor.remove ( *this );
|
||||
if ( pGlobal->pCurrent == this ) {
|
||||
// cancel from callback, or while lookup in progress
|
||||
pGlobal->pCurrent = 0;
|
||||
}
|
||||
else {
|
||||
// cancel before lookup starts
|
||||
pGlobal->labor.remove ( *this );
|
||||
}
|
||||
this->pending = false;
|
||||
}
|
||||
this->pending = false;
|
||||
}
|
||||
assert(this->engine.refcount>0);
|
||||
last = 0==--this->engine.refcount;
|
||||
}
|
||||
if(last) {
|
||||
delete &this->engine;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,15 +421,21 @@ void ipAddrToAsciiTransactionPrivate::ipAddrToAscii (
|
||||
const osiSockAddr & addrIn, ipAddrToAsciiCallBack & cbIn )
|
||||
{
|
||||
bool success;
|
||||
ipAddrToAsciiGlobal *pGlobal = this->engine.pEngine;
|
||||
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->engine.mutex );
|
||||
// put some reasonable limit on queue expansion
|
||||
if ( !this->pending && engine.labor.count () < 16u ) {
|
||||
epicsGuard < epicsMutex > guard ( pGlobal->mutex );
|
||||
|
||||
if (this->engine.released) {
|
||||
errlogPrintf("Warning: ipAddrToAscii on transaction with release()'d ipAddrToAsciiEngine");
|
||||
success = false;
|
||||
|
||||
} else if ( !this->pending && pGlobal->labor.count () < 16u ) {
|
||||
// put some reasonable limit on queue expansion
|
||||
this->addr = addrIn;
|
||||
this->pCB = & cbIn;
|
||||
this->pending = true;
|
||||
this->engine.labor.add ( *this );
|
||||
pGlobal->labor.add ( *this );
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
@@ -354,7 +444,7 @@ void ipAddrToAsciiTransactionPrivate::ipAddrToAscii (
|
||||
}
|
||||
|
||||
if ( success ) {
|
||||
this->engine.laborEvent.signal ();
|
||||
pGlobal->laborEvent.signal ();
|
||||
}
|
||||
else {
|
||||
char autoNameTmp[256];
|
||||
@@ -371,7 +461,7 @@ osiSockAddr ipAddrToAsciiTransactionPrivate::address () const
|
||||
|
||||
void ipAddrToAsciiTransactionPrivate::show ( unsigned level ) const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->engine.mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->engine.pEngine->mutex );
|
||||
char ipAddr [64];
|
||||
sockAddrToDottedIP ( &this->addr.sa, ipAddr, sizeof ( ipAddr ) );
|
||||
printf ( "ipAddrToAsciiTransactionPrivate for address %s\n", ipAddr );
|
||||
|
||||
@@ -44,6 +44,10 @@ public:
|
||||
static ipAddrToAsciiEngine & allocate ();
|
||||
protected:
|
||||
virtual ~ipAddrToAsciiEngine () = 0;
|
||||
public:
|
||||
#ifdef EPICS_PRIVATE_API
|
||||
static void cleanup();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // ifdef ipAddrToAsciiAsynchronous_h
|
||||
|
||||
@@ -11,6 +11,7 @@ TOP=../../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_LIBS += Com
|
||||
PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32
|
||||
|
||||
TESTPROD_HOST += epicsUnitTestTest
|
||||
epicsUnitTestTest_SRCS += epicsUnitTestTest.c
|
||||
@@ -204,6 +205,10 @@ epicsStackTraceTest_SRCS += epicsStackTraceTest.c
|
||||
testHarness_SRCS += epicsStackTraceTest.c
|
||||
TESTS += epicsStackTraceTest
|
||||
|
||||
TESTPROD_HOST += ipAddrToAsciiTest
|
||||
ipAddrToAsciiTest_SRCS += ipAddrToAsciiTest.cpp
|
||||
testHarness_SRCS += ipAddrToAsciiTest.cpp
|
||||
TESTS += ipAddrToAsciiTest
|
||||
|
||||
# The testHarness runs all the test programs in a known working order.
|
||||
testHarness_SRCS += epicsRunLibComTests.c
|
||||
|
||||
@@ -43,12 +43,13 @@ int epicsThreadPrivateTest(void);
|
||||
int epicsThreadTest(void);
|
||||
int epicsTimerTest(void);
|
||||
int epicsTimeTest(void);
|
||||
int epicsTypesTest(void);
|
||||
int epicsInlineTest(void);
|
||||
int macDefExpandTest(void);
|
||||
#ifdef __rtems__
|
||||
int epicsTimeZoneTest(void);
|
||||
#endif
|
||||
int epicsTypesTest(void);
|
||||
int epicsInlineTest(void);
|
||||
int ipAddrToAsciiTest(void);
|
||||
int macDefExpandTest(void);
|
||||
int macLibTest(void);
|
||||
int ringBytesTest(void);
|
||||
int ringPointerTest(void);
|
||||
@@ -79,6 +80,7 @@ void epicsRunLibComTests(void)
|
||||
runTest(epicsEnvTest);
|
||||
runTest(epicsErrlogTest);
|
||||
runTest(epicsEventTest);
|
||||
runTest(epicsInlineTest);
|
||||
runTest(epicsMathTest);
|
||||
runTest(epicsMessageQueueTest);
|
||||
runTest(epicsMMIOTest);
|
||||
@@ -95,14 +97,12 @@ void epicsRunLibComTests(void)
|
||||
runTest(epicsThreadPriorityTest);
|
||||
runTest(epicsThreadPrivateTest);
|
||||
runTest(epicsTimeTest);
|
||||
runTest(epicsTypesTest);
|
||||
runTest(epicsInlineTest);
|
||||
runTest(macDefExpandTest);
|
||||
|
||||
#ifdef __rtems__
|
||||
runTest(epicsTimeZoneTest);
|
||||
#endif
|
||||
|
||||
runTest(epicsTypesTest);
|
||||
runTest(ipAddrToAsciiTest);
|
||||
runTest(macDefExpandTest);
|
||||
runTest(macLibTest);
|
||||
runTest(ringBytesTest);
|
||||
runTest(ringPointerTest);
|
||||
|
||||
165
src/libCom/test/ipAddrToAsciiTest.cpp
Normal file
165
src/libCom/test/ipAddrToAsciiTest.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2017 Michael Davidsaver
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsGuard.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "ipAddrToAsciiAsynchronous.h"
|
||||
|
||||
#include "epicsUnitTest.h"
|
||||
#include "testMain.h"
|
||||
|
||||
namespace {
|
||||
|
||||
typedef epicsGuard<epicsMutex> Guard;
|
||||
typedef epicsGuardRelease<epicsMutex> UnGuard;
|
||||
|
||||
struct CB : public ipAddrToAsciiCallBack
|
||||
{
|
||||
const char *name;
|
||||
epicsMutex mutex;
|
||||
epicsEvent starter, blocker, complete;
|
||||
bool started, cont, done;
|
||||
CB(const char *name) : name(name), started(false), cont(false), done(false) {}
|
||||
virtual ~CB() {}
|
||||
virtual void transactionComplete ( const char * pHostName )
|
||||
{
|
||||
Guard G(mutex);
|
||||
started = true;
|
||||
starter.signal();
|
||||
testDiag("In transactionComplete(%s) for %s", pHostName, name);
|
||||
while(!cont) {
|
||||
UnGuard U(G);
|
||||
if(!blocker.wait(2.0))
|
||||
break;
|
||||
}
|
||||
done = true;
|
||||
complete.signal();
|
||||
}
|
||||
void waitStart()
|
||||
{
|
||||
Guard G(mutex);
|
||||
while(!started) {
|
||||
UnGuard U(G);
|
||||
if(!starter.wait(2.0))
|
||||
break;
|
||||
}
|
||||
}
|
||||
void poke()
|
||||
{
|
||||
testDiag("Poke");
|
||||
Guard G(mutex);
|
||||
cont = true;
|
||||
blocker.signal();
|
||||
}
|
||||
void finish()
|
||||
{
|
||||
testDiag("Finish");
|
||||
Guard G(mutex);
|
||||
while(!done) {
|
||||
UnGuard U(G);
|
||||
if(!complete.wait(2.0))
|
||||
break;
|
||||
}
|
||||
testDiag("Finished");
|
||||
}
|
||||
};
|
||||
|
||||
// ensure that lookup of 127.0.0.1 works
|
||||
void doLookup(ipAddrToAsciiEngine& engine)
|
||||
{
|
||||
testDiag("In doLookup");
|
||||
|
||||
ipAddrToAsciiTransaction& trn(engine.createTransaction());
|
||||
CB cb("cb");
|
||||
osiSockAddr addr;
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.ia.sin_port = htons(42);
|
||||
|
||||
testDiag("Start lookup");
|
||||
trn.ipAddrToAscii(addr, cb);
|
||||
cb.poke();
|
||||
cb.finish();
|
||||
testOk1(cb.cont);
|
||||
testOk1(cb.done);
|
||||
|
||||
trn.release();
|
||||
}
|
||||
|
||||
// Test cancel of pending transaction
|
||||
void doCancel()
|
||||
{
|
||||
testDiag("In doCancel");
|
||||
|
||||
ipAddrToAsciiEngine& engine1(ipAddrToAsciiEngine::allocate());
|
||||
ipAddrToAsciiEngine& engine2(ipAddrToAsciiEngine::allocate());
|
||||
|
||||
ipAddrToAsciiTransaction& trn1(engine1.createTransaction()),
|
||||
& trn2(engine2.createTransaction());
|
||||
testOk1(&trn1!=&trn2);
|
||||
CB cb1("cb1"), cb2("cb2");
|
||||
|
||||
osiSockAddr addr;
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.ia.sin_port = htons(42);
|
||||
|
||||
// ensure that the worker thread is blocked with a transaction from engine1
|
||||
testDiag("Start lookup1");
|
||||
trn1.ipAddrToAscii(addr, cb1);
|
||||
testDiag("Wait start1");
|
||||
cb1.waitStart();
|
||||
|
||||
testDiag("Start lookup2");
|
||||
trn2.ipAddrToAscii(addr, cb2);
|
||||
|
||||
testDiag("release engine2, implicitly cancels lookup2");
|
||||
engine2.release();
|
||||
|
||||
cb2.poke();
|
||||
testDiag("Wait for lookup2 timeout");
|
||||
cb2.finish();
|
||||
testOk1(!cb2.done);
|
||||
|
||||
testDiag("Complete lookup1");
|
||||
cb1.poke();
|
||||
cb1.finish();
|
||||
testOk1(cb1.done);
|
||||
|
||||
engine1.release();
|
||||
|
||||
trn1.release();
|
||||
trn2.release();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MAIN(ipAddrToAsciiTest)
|
||||
{
|
||||
testPlan(5);
|
||||
{
|
||||
ipAddrToAsciiEngine& engine(ipAddrToAsciiEngine::allocate());
|
||||
doLookup(engine);
|
||||
engine.release();
|
||||
}
|
||||
doCancel();
|
||||
// TODO: somehow test cancel of in-progress callback
|
||||
// allow time for any un-canceled transcations to crash us...
|
||||
epicsThreadSleep(1.0);
|
||||
|
||||
#ifdef __linux__
|
||||
ipAddrToAsciiEngine::cleanup();
|
||||
#endif
|
||||
|
||||
return testDone();
|
||||
}
|
||||
@@ -65,7 +65,7 @@ static void ovcheck(void)
|
||||
|
||||
MAIN(macLibTest)
|
||||
{
|
||||
testPlan(89);
|
||||
testPlan(91);
|
||||
|
||||
if (macCreateHandle(&h, NULL))
|
||||
testAbort("macCreateHandle() failed");
|
||||
@@ -203,6 +203,9 @@ MAIN(macLibTest)
|
||||
/* STR2 = "VAL2" */
|
||||
check("${FOO}", " VAL2");
|
||||
|
||||
check("$(FOO)$(FOO1)", "!VAL2$(FOO1,undefined)");
|
||||
check("$(FOO1)$(FOO)", "!$(FOO1,undefined)VAL2");
|
||||
|
||||
macPutValue(h, "BAR","${FOO}");
|
||||
/* FOO = "${BAR}" */
|
||||
/* BAR = "${FOO}" */
|
||||
|
||||
Reference in New Issue
Block a user