Compare commits
197 Commits
R3.13.0-be
...
R3.13.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8a8f4c0e1 | ||
|
|
7a809e2e1e | ||
|
|
fdbfab2da2 | ||
|
|
50e53c3b60 | ||
|
|
6c974f9cf5 | ||
|
|
a48efbd861 | ||
|
|
2752749f5e | ||
|
|
d3bce294c3 | ||
|
|
6a51de27e5 | ||
|
|
779eea486e | ||
|
|
2b67d03514 | ||
|
|
830d2ff061 | ||
|
|
84b35b89ef | ||
|
|
6d0f7e878a | ||
|
|
951d97e7ff | ||
|
|
ccb8a554ab | ||
|
|
2cc65e1912 | ||
|
|
84544919cf | ||
|
|
f29a18fb06 | ||
|
|
373963601e | ||
|
|
03225a337e | ||
|
|
009ec62aab | ||
|
|
5f79145db6 | ||
|
|
592eb7a0d5 | ||
|
|
8d33c7127c | ||
|
|
19a8c56a69 | ||
|
|
daeb1247d8 | ||
|
|
fce5bb7398 | ||
|
|
e0122a1f18 | ||
|
|
fe782e3e4e | ||
|
|
5824a6096c | ||
|
|
4908e28d31 | ||
|
|
423e24fe8b | ||
|
|
db49a2babb | ||
|
|
e11c120f6b | ||
|
|
9155de5b30 | ||
|
|
599b22b70b | ||
|
|
6509cf77bf | ||
|
|
3c6ac06cff | ||
|
|
eba09bd6af | ||
|
|
b95644e9d7 | ||
|
|
6b415ddb49 | ||
|
|
88f27261f0 | ||
|
|
de29d6868d | ||
|
|
6e143c1b3c | ||
|
|
ffe28c21d6 | ||
|
|
4abdee5635 | ||
|
|
ae42cd5dfd | ||
|
|
dbd9309810 | ||
|
|
5d78536ad5 | ||
|
|
c41f2e9514 | ||
|
|
757be61d57 | ||
|
|
df10654f77 | ||
|
|
e7773db7a7 | ||
|
|
9f6dc20fd8 | ||
|
|
f654800370 | ||
|
|
f810436bb1 | ||
|
|
5593db0caf | ||
|
|
e9a04e688f | ||
|
|
b8fe2ed007 | ||
|
|
115f2b8a1e | ||
|
|
fefb8454c7 | ||
|
|
e4cf1df857 | ||
|
|
f3bd38caca | ||
|
|
c104460654 | ||
|
|
fc3db2c3bf | ||
|
|
41e02220d1 | ||
|
|
8f5061b28e | ||
|
|
5898d94c4c | ||
|
|
b2ced4889b | ||
|
|
a65e5f1f73 | ||
|
|
839b8bdb5f | ||
|
|
421d98a936 | ||
|
|
95b6d4a998 | ||
|
|
cc2ea961d7 | ||
|
|
3a0de109a3 | ||
|
|
41aad467a6 | ||
|
|
ebf6c4932a | ||
|
|
b587d3639f | ||
|
|
7408f7f29f | ||
|
|
e2baae4281 | ||
|
|
b61b816c49 | ||
|
|
5257374a73 | ||
|
|
f732ff2505 | ||
|
|
8e2e15194a | ||
|
|
4a3993c4e5 | ||
|
|
f11dadd032 | ||
|
|
881cbd60e3 | ||
|
|
598e87d598 | ||
|
|
6e8fc4f9c1 | ||
|
|
1be3c39e50 | ||
|
|
fc48d2dd1d | ||
|
|
11084a5dfc | ||
|
|
7946e9b921 | ||
|
|
2a1f06cd2a | ||
|
|
ccf3271fe1 | ||
|
|
c99ee0317c | ||
|
|
5bf13da02c | ||
|
|
cbd5d9a36e | ||
|
|
bb8e8f46cb | ||
|
|
6b6e5e7515 | ||
|
|
0b0b23c6d6 | ||
|
|
1ed2559cc3 | ||
|
|
9a068b824d | ||
|
|
32a847087d | ||
|
|
67fbf5b746 | ||
|
|
a0e8290c50 | ||
|
|
7cde4f8f2b | ||
|
|
437142b5bb | ||
|
|
42adbd20c8 | ||
|
|
85a2ef6e4d | ||
|
|
62ce79e147 | ||
|
|
3a840f6e2f | ||
|
|
69c62573b0 | ||
|
|
e1e8a34b2f | ||
|
|
13c9ae5fe3 | ||
|
|
6912ff4929 | ||
|
|
0e387c8936 | ||
|
|
e8e3b5226e | ||
|
|
b87f049c2d | ||
|
|
0d7698e0d4 | ||
|
|
ebbaee5ed2 | ||
|
|
bff266bef3 | ||
|
|
1d6f9f80f6 | ||
|
|
8a298ab07c | ||
|
|
7f317f4d55 | ||
|
|
50b19bc74f | ||
|
|
9f35f8043e | ||
|
|
19091f245b | ||
|
|
0bc395108d | ||
|
|
2b6367e1d4 | ||
|
|
6fb8477b3a | ||
|
|
39c22d2ee0 | ||
|
|
721840498c | ||
|
|
56e35d8305 | ||
|
|
a42a244aed | ||
|
|
b8dba0a4ad | ||
|
|
fe9f9b91fb | ||
|
|
206a04e15f | ||
|
|
db11fd957d | ||
|
|
2517d52437 | ||
|
|
f85aba61ed | ||
|
|
147403b0e5 | ||
|
|
afa84f396b | ||
|
|
9888b965d8 | ||
|
|
c3e2f58d96 | ||
|
|
697200e942 | ||
|
|
33b940562e | ||
|
|
08f2298215 | ||
|
|
8c992ed466 | ||
|
|
c442950e5f | ||
|
|
0a5dffc069 | ||
|
|
744a0de15d | ||
|
|
7c42f005db | ||
|
|
652cb0d66c | ||
|
|
9f77fbccd1 | ||
|
|
de2864a5a5 | ||
|
|
2caf1628ca | ||
|
|
f1865a507c | ||
|
|
8013fecb61 | ||
|
|
8d6deea83d | ||
|
|
da3eed2a6f | ||
|
|
5de817b531 | ||
|
|
a173792b1f | ||
|
|
6af690f524 | ||
|
|
1891940018 | ||
|
|
6adb68d7d6 | ||
|
|
c1225d880e | ||
|
|
017686e0f6 | ||
|
|
f61f401683 | ||
|
|
3a5e5fc5d7 | ||
|
|
8d0712bea4 | ||
|
|
0804f7fb08 | ||
|
|
7a8878dec6 | ||
|
|
92ae7b14c4 | ||
|
|
eda3aae608 | ||
|
|
8e363122b3 | ||
|
|
ff378e17c9 | ||
|
|
5e1157d363 | ||
|
|
d3c6310bb1 | ||
|
|
5c4d82cacc | ||
|
|
414c8ed603 | ||
|
|
603c598e14 | ||
|
|
a3cad9563f | ||
|
|
cb95ba41ac | ||
|
|
8e000eb634 | ||
|
|
b00f152456 | ||
|
|
566d70bf9c | ||
|
|
bc6bf59bda | ||
|
|
6fcbfa15b3 | ||
|
|
121a2dc9ae | ||
|
|
35f9a872f7 | ||
|
|
0efb9a0c8c | ||
|
|
63da245439 | ||
|
|
8b83afc1bb | ||
|
|
54e6f9aed1 | ||
|
|
4c99a53852 |
4
Makefile
4
Makefile
@@ -28,7 +28,3 @@ built_release:
|
||||
@echo TOP: Creating Fully Built Release...
|
||||
@./MakeRelease -b $(INSTALL_LOCATION)
|
||||
|
||||
uninstall::
|
||||
@DIR1=`pwd`;cd $(INSTALL_LOCATION);DIR2=`pwd`;cd $$DIR1;\
|
||||
if [ "$$DIR1" != "$$DIR2" ]; then rm -fr $(INSTALL_LOCATION)/config; fi
|
||||
|
||||
|
||||
14
README.Linux
14
README.Linux
@@ -1,16 +1,10 @@
|
||||
Special Notes on Linux
|
||||
1) The epics makefiles use GNU make which is the make that comes
|
||||
with Linux. You need to make a link from make to gnumake and
|
||||
have it in your path. After you have defined the EPICS environement
|
||||
variable, you can use:
|
||||
|
||||
ln -s /usr/bin/make $EPICS/base/tools/gnumake
|
||||
At this point, support for Linux only involves channel access
|
||||
clients. Since Vxworks is not available for Linux, you must
|
||||
use other platforms for developing server side code.
|
||||
|
||||
2) At this point, support for Linux only involves channel access
|
||||
clients. Since Vxworks is not available for Linux, you must
|
||||
use other platforms for developing server side code.
|
||||
|
||||
3) You MUST start caRepeater by hand before running a client.
|
||||
You MUST start caRepeater by hand before running a client.
|
||||
Prior to running a client, you must run:
|
||||
|
||||
caRepeater &
|
||||
|
||||
44
README.Perl
Normal file
44
README.Perl
Normal file
@@ -0,0 +1,44 @@
|
||||
Perl
|
||||
====
|
||||
|
||||
A number of shell scripts are now Perl scripts,
|
||||
most important:
|
||||
|
||||
tools/installEpics.pl
|
||||
include/makeEpicsVersion.pl
|
||||
libCom/bldEnvData.pl
|
||||
libCom/makeStatSymTbl.pl
|
||||
sequencer/makeVersion.pl
|
||||
|
||||
WIN32 also uses
|
||||
tools/cp.pl, mv.pl, rm.pl, mkdir.pl
|
||||
which should behave like the UNIX cp, mv, rm, rmdir.
|
||||
All systems could use the Perl versions but that seems
|
||||
to be overkill for UNIX.
|
||||
|
||||
Advantages:
|
||||
* no need for ls, date, basename, grep, awk, sed, ...,
|
||||
which made the make UNIX-specific.
|
||||
* Perl is currently available for Unix, OS/2, WIN32, VMS
|
||||
and the scripts should work on all those systems
|
||||
|
||||
Disadvantage:
|
||||
* You have to get Perl, look e.g. at http://www.perl.com
|
||||
* Perl version 5.003_02 works, we don't know about earlier versions.
|
||||
|
||||
|
||||
Compile Perl:
|
||||
No big deal,
|
||||
* on UNIX say 'configure' and 'gnumake',
|
||||
* on Windows use MX Visual C++,
|
||||
use File/Open Workspace to open the Makefile {PERL}/perl5i.mak,
|
||||
use Build/Batch build to select eiher the Release or Debug targets.
|
||||
|
||||
You can do the same with the Makefile {Perl}/Ext/WIN32/win32.mak
|
||||
- nice tools but not necessary for EPICS.
|
||||
|
||||
Then call {PERL}/bin/perlw32-install.bat
|
||||
|
||||
In any case, read the texts that come with perl!
|
||||
|
||||
|
||||
82
README.WIN32
82
README.WIN32
@@ -1,17 +1,19 @@
|
||||
Compiling EPICS on WIN32 (Windows95/NT)
|
||||
---------------------------------------
|
||||
|
||||
-kuk- 11/18/96 questions & comments please
|
||||
mailto:kasemir@atdiv.lanl.gov
|
||||
Original port of EPICS base to WIN32 (Windows95/NT)
|
||||
was done by Kay-Uwe Kasemir 11/96
|
||||
|
||||
questions & comments please mail to johill@lanl.gov
|
||||
|
||||
0) what you will get
|
||||
--------------------
|
||||
|
||||
Right now this port of EPICS to WIN32 should allow you to
|
||||
|
||||
* compile almost all EPICS base using Tornado, MS Visual C
|
||||
and some additional tools: gnumake, a UNIX-like shell, awk, sed, ...
|
||||
(See below where to get these.)
|
||||
* compile almost all of EPICS base using {Tornado, MS Visual C, perl,
|
||||
GNU make} (only {MS Visual C, perl, GNU make} if you prefer
|
||||
to compile only the host portions of EPICS base).
|
||||
* load EPICS on a PC IOC (486, pentium),
|
||||
load simple databases
|
||||
(no drivers/devices for real I/O available, yet.
|
||||
@@ -30,73 +32,41 @@ Right now this port of EPICS to WIN32 should allow you to
|
||||
To compiler EPICS on WIN32, we need
|
||||
|
||||
WindRiver Systems Tornado (used: 1.0)
|
||||
Microsoft Visual C (used: 4.0)
|
||||
Microsoft Visual C (used: 4.0)
|
||||
|
||||
and some tools:
|
||||
|
||||
a Unix-like shell
|
||||
gnumake
|
||||
basename
|
||||
date
|
||||
mv
|
||||
touch
|
||||
sort
|
||||
gnu make
|
||||
perl
|
||||
|
||||
All the above except. the shell are available 'on the net'
|
||||
The perl interpreter and gnu make are available 'on the net'
|
||||
as sources which compile with MS Visual C++.
|
||||
If you cannot/don't want to find them, contact me, please!
|
||||
|
||||
I could not find a shell that's fully operational.
|
||||
The best one seems to be the Cygnus bash for WIN32, though it
|
||||
still has errors and doesn't come with sources that compile
|
||||
under MS VC++.
|
||||
I use a small self-written shell called knts,
|
||||
again: Contact me if you need it.
|
||||
|
||||
* The final solution to make the shell, basename, date, ...
|
||||
* obsolete:
|
||||
* Use
|
||||
* 1) no shell scripts
|
||||
* 2) Perl which is available for Unix and WIN32
|
||||
|
||||
In addition we need some binaries that I have no sources
|
||||
for, yet, but that come with Tornado if and only if you
|
||||
INSTALL THE FULL PACKAGE (!)
|
||||
Including the 'WTX Test Suite i386/i486'
|
||||
(under "Select Sub-components" when installing Tornado)
|
||||
|
||||
You should find in your <Tornado>/host/x86-win32/bin dir:
|
||||
|
||||
awk, cat, cp, rm, mkdir
|
||||
|
||||
(There is also a bash and a GNU-make which are really poor,
|
||||
and WindRiver told me that they do not consider to support
|
||||
those in the future, so I no longer use them.)
|
||||
|
||||
2) set environment variables
|
||||
----------------------------
|
||||
|
||||
Your path should include:
|
||||
- The EPICS-binaries that we are about to build in base/bin/WIN32
|
||||
- The NTtools that you've built in step 1
|
||||
- The EPICS-binaries that we are about to build in <EPICS>base/bin/WIN32
|
||||
- The System (for me it's in NT40...)
|
||||
- The MS Visual C compiler binaries
|
||||
- The Tornado binaries
|
||||
|
||||
Check with e.g.:
|
||||
|
||||
/users/kay/Src/epics/nttools >echo $Path
|
||||
c:\users\kay\src\epics\base\bin\WIN32;c:\users\kay\src\epics\NTtools\bin;C:\NT40
|
||||
\system32;C:\NT40;c:\msdev\bin;C:\users\Tornado\host\x86-win32\bin
|
||||
>echo %Path%
|
||||
C:\WINNT35.0\system32;
|
||||
C:\WINNT35.0;
|
||||
c:\msdev\bin;
|
||||
c:\perl5\bin;
|
||||
c:\make-3.75\WinRel;
|
||||
c:\epics\base\bin\win32
|
||||
|
||||
On NT, $Path is defined by the operatin system, on Win95, it's $PATH instead.
|
||||
knts tries to use PATH and falls back on Path,
|
||||
what should wok on both systems.
|
||||
On NT, "Path" is defined by the operatin system, on Win95, it's "PATH" instead.
|
||||
|
||||
MS Visual C and Tornado should be installed properly with
|
||||
these env. variables set:
|
||||
|
||||
WIND_BASE=c:\usersTornado
|
||||
WIND_BASE=c:\Tornado
|
||||
WIND_HOST_TYPE=x86-win32
|
||||
|
||||
This way the EPICS makesystem can locate Tornado
|
||||
@@ -116,6 +86,7 @@ For EPICS, set:
|
||||
|
||||
# select host arch to build:
|
||||
HOST_ARCH=WIN32
|
||||
HOME=??? # if you use $(HOME)/EPICS_CONFIG
|
||||
|
||||
EPICS_CA_ADDR_LIST 128.165.32.255 (addr of WIN32 host)
|
||||
EPICS_CA_AUTO_CA_ADDR_LIST NO
|
||||
@@ -126,20 +97,13 @@ EPICS_CA_SERVER_PORT 5064
|
||||
EPICS_TS_MIN_WEST 420 (Germany: -120)
|
||||
|
||||
|
||||
To debug knts, set KNTS to 5:
|
||||
KNTS=5
|
||||
export KNTS
|
||||
|
||||
You should do this, however, only if you really want the debugging info.
|
||||
|
||||
|
||||
3) building EPICS
|
||||
-----------------
|
||||
|
||||
Prepare apx. 2 ltr. Tee and type:
|
||||
|
||||
cd <epics>/base
|
||||
gnumake
|
||||
make
|
||||
|
||||
Watch for errors and send them to me.
|
||||
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
#
|
||||
# supplement README for HP700 and Alpha OSF/1 builds
|
||||
# supplement README for HP700
|
||||
#
|
||||
# Johnny Tang 5-29-97
|
||||
#
|
||||
# M. Anderson and J. Tang
|
||||
|
||||
1. VxWorks 5.2 for HP-UX
|
||||
|
||||
- Directory permissions may not be correct across multiple machines, so a
|
||||
- Make sure that you have set VX_DIR and VX_GNU to your
|
||||
VxWorks root directory.
|
||||
|
||||
% chmod -R ugo+rw base extensions
|
||||
- Under $(VX_DIR), create a soft link:
|
||||
hp700.68k -> hp9700.68k
|
||||
|
||||
might be necessary.
|
||||
2. Modify base/config/CONFIG_SITE file
|
||||
|
||||
- ANSI=HPACC
|
||||
- STANDARD=HPCC
|
||||
- CPLUSPLUS=G++
|
||||
|
||||
3. HP native c++ compiler has problem to handle the head files
|
||||
in which a inline function is used in conjuction with template
|
||||
|
||||
base/src/cas, the portable CA server can't be compiled successfully
|
||||
because of the above limitation.
|
||||
|
||||
This problem can be resolved by spliting the function declarations
|
||||
from the inline code in the files in base/src/cxxTemplates.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
----------------------------------------------------------------------------
|
||||
EPICS R3.12.2 Notes for Solaris
|
||||
EPICS Notes for Solaris
|
||||
- By Andrew Johnson
|
||||
|
||||
updated 12-16-96 by Jeff Hill
|
||||
|
||||
@@ -24,8 +24,8 @@ include $(EPICS_BASE)/config/CONFIG.$(T_A)
|
||||
|
||||
# User specific definitions
|
||||
#
|
||||
-include $(HOME)/.EPICS_CONFIG
|
||||
-include $(HOME)/.EPICS_CONFIG.$(HOST_ARCH)
|
||||
-include $(HOME)/EPICS_CONFIG
|
||||
-include $(HOME)/EPICS_CONFIG.$(HOST_ARCH)
|
||||
|
||||
# All EPICS options other than BUILD_TYPE
|
||||
# may be overridden here.
|
||||
|
||||
@@ -80,8 +80,8 @@ VX_INCLUDES = -I. -I.. $(USR_INCLUDES) -I$(INSTALL_INCLUDE) -I$(EPICS_BASE_INCLU
|
||||
|
||||
# Warnings
|
||||
#At some time we should turn on pedantic
|
||||
#VX_WARN_YES = -Wall -pedantic
|
||||
VX_WARN_YES = -Wall
|
||||
VX_WARN_YES = -Wall -pedantic -ansi
|
||||
#VX_WARN_YES = -Wall
|
||||
VX_WARN_NO =
|
||||
VX_WARN_FLAGS = $(VX_WARN_$(VX_WARN))
|
||||
|
||||
@@ -93,8 +93,6 @@ VX_CFLAGS = $(VX_OPT_FLAGS) $(VX_WARN_FLAGS) \
|
||||
$(VX_INCLUDES) $(VX_OP_SYS_FLAGS)
|
||||
VX_CXXFLAGS += $(VX_CFLAGS)
|
||||
|
||||
VX_LDFLAGS = -o
|
||||
|
||||
TARGET_CFLAGS = $($(basename $@)_CFLAGS)
|
||||
TARGET_CXXFLAGS = $($(basename $@)_CXXFLAGS)
|
||||
TARGET_LDFLAGS = $($(basename $@)_LDFLAGS)
|
||||
@@ -104,16 +102,20 @@ TARGET_SNCFLAGS = $($(basename $@)_SNCFLAGS)
|
||||
CFLAGS = $(TARGET_CFLAGS) $(USR_CFLAGS) $(ARCH_DEP_CFLAGS) $(VX_CFLAGS)
|
||||
CXXFLAGS = $(TARGET_CXXFLAGS) $(USR_CXXFLAGS) $(ARCH_DEP_CXXFLAGS) $(VX_CXXFLAGS)
|
||||
LDFLAGS = $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(ARCH_DEP_LDFLAGS) $(VX_LDFLAGS)
|
||||
CXXLDFLAGS = $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(ARCH_DEP_CXXLDFLAGS) $(VX_LDFLAGS)
|
||||
LDLIBS = $(TARGET_LDLIBS) $(USR_LDLIBS) $(ARCH_DEP_LDLIBS) $(VX_LDLIBS)
|
||||
CXXLDLIBS = $(TARGET_LDLIBS) $(USR_CXXLDLIBS) $(ARCH_DEP_LDLIBS) $(VX_LDLIBS)
|
||||
CXXLDFLAGS = $(TARGET_LDFLAGS) $(USR_CXXLDFLAGS) $(ARCH_DEP_CXXLDFLAGS) $(VX_LDFLAGS)
|
||||
CPPFLAGS += $(TARGET_CPPFLAGS) $(USR_CPPFLAGS)
|
||||
# Build compile line here
|
||||
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
|
||||
LINK.c = $(LD) $(LDFLAGS)
|
||||
LINK.c = $(LD) $(LDFLAGS) -o
|
||||
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||
LINK.cc = $(LD_CXX) $(CXXLDFLAGS)
|
||||
LINK.cc = $(LD_CXX) $(CXXLDFLAGS) -o
|
||||
|
||||
CPPSNCFLAGS = $(VX_INCLUDES)
|
||||
|
||||
DEPENDS_RULE.c = -$(COMPILE.c) -M $(SRCS.c) >> .DEPENDS
|
||||
DEPENDS_RULE.cc = -$(COMPILE.cc) -M $(SRCS.cc) >> .DEPENDS
|
||||
|
||||
# Allow site host architecture specific overrides
|
||||
-include $(EPICS_BASE)/config/CONFIG_SITE.$(BUILD_TYPE).$(ARCH_CLASS).$(HOST_ARCH)
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
# Unix Compiler and other Utilities
|
||||
OLDINSTALL = echo CONFIG.Vx.486 OLDINSTALL
|
||||
|
||||
MV=mv
|
||||
RM=rm -f
|
||||
CP=cp
|
||||
RMDIR=rm -rf
|
||||
MKDIR=mkdir
|
||||
CHMOD = "/bin/chmod"
|
||||
WHAT = what
|
||||
CP =$(PERL) $(EPICS_BASE)/src/tools/cp.pl
|
||||
MV =$(PERL) $(EPICS_BASE)/src/tools/mv.pl
|
||||
RM =$(PERL) $(EPICS_BASE)/src/tools/rm.pl -f
|
||||
MKDIR=$(PERL) $(EPICS_BASE)/src/tools/mkdir.pl
|
||||
RMDIR=$(PERL) $(EPICS_BASE)/src/tools/rm.pl -rf
|
||||
CHMOD=echo
|
||||
WHAT=echo
|
||||
|
||||
# overrides defines in CONFIG_SITE that don't fit Tornado
|
||||
#
|
||||
|
||||
@@ -3,54 +3,69 @@
|
||||
# The current make-system for WIN32
|
||||
# needs
|
||||
# * gnumake (OK, sources for WIN32 are available)
|
||||
# * several UNIX tools: sed, grep, ... (dito)
|
||||
# * Perl (e.g. from www.perl.com )
|
||||
# * a UNIX-like shell (ouch!)
|
||||
#
|
||||
# I found no fully operational shell and no sources for WIN32 so far,
|
||||
# Cygnus' bash e.g. cannot handle this:
|
||||
# (echo a>a; echo b>>a)
|
||||
# Right now I use the knts that I wrote and simplified scripts.
|
||||
# Jeff eliminated many shell-lines in Makefile.*,
|
||||
# the final solution could be:
|
||||
# 1) replace shell, awk, grep, sed, ... by Perl!
|
||||
# 2) use C code
|
||||
# Jeff eliminated many shell-lines in Makefile.*.
|
||||
#
|
||||
|
||||
# Set this to the UNIX-like shell that you have:
|
||||
SHELL=knts
|
||||
#
|
||||
# it is now possible to just use the DOS shell
|
||||
#
|
||||
#SHELL=knts
|
||||
|
||||
# Use std path variables from ms
|
||||
HOME = $(HOMEDRIVE)$(HOMEPATH)
|
||||
|
||||
# BUILD_TYPE
|
||||
# Currently either Vx or Host (latter used to be Unix)
|
||||
# Currently either Vx or Host (latter used to be Unix
|
||||
BUILD_TYPE=Host
|
||||
|
||||
#
|
||||
# optimize/debug flags
|
||||
#
|
||||
HOST_OPT = YES
|
||||
# -Ox : maximum optimizations
|
||||
# -Wn ; use this warning level (all warnings at level 4)
|
||||
CXX_OPT_FLAGS_YES = -Ox -W1
|
||||
# -Zi : include debugging info in object files
|
||||
CXX_OPT_FLAGS_NO = -Zi -W1
|
||||
CXX_OPT_FLAGS = $(CXX_OPT_FLAGS_$(HOST_OPT))
|
||||
LINK_OPT_FLAGS_YES =
|
||||
LINK_OPT_FLAGS_NO = -debug
|
||||
LINK_OPT_FLAGS = $(LINK_OPT_FLAGS_$(HOST_OPT))
|
||||
|
||||
# to identify the general architecture class:
|
||||
# should be BSD, SYSV, WIN32, ...
|
||||
# is: WIN32, sun4, hpux, linux, ...
|
||||
#
|
||||
ARCH_CLASS=WIN32
|
||||
|
||||
|
||||
EXE=.exe
|
||||
OBJ=.obj
|
||||
|
||||
# ifdef WIN32 looks better that ifeq ($(ARCH_CLASS),WIN32) ??
|
||||
WIN32=1
|
||||
|
||||
# Compiler and utility invocation (supply path to compiler here)
|
||||
# (with warning flags built in)
|
||||
# Paths to compilers
|
||||
YACC = $(EYACC)
|
||||
LEX = $(ELEX)
|
||||
CC = cl -nologo
|
||||
MV=mv
|
||||
RM=rm -f
|
||||
MKDIR=mkdir
|
||||
RMDIR=rm -rf
|
||||
WHAT = echo
|
||||
YACC = $(EYACC)
|
||||
LEX = $(ELEX)
|
||||
CC = cl -nologo
|
||||
CP = $(PERL) $(EPICS_BASE)/src/tools/cp.pl
|
||||
MV = $(PERL) $(EPICS_BASE)/src/tools/mv.pl
|
||||
RM = $(PERL) $(EPICS_BASE)/src/tools/rm.pl -f
|
||||
MKDIR = $(PERL) $(EPICS_BASE)/src/tools/mkdir.pl
|
||||
RMDIR = $(PERL) $(EPICS_BASE)/src/tools/rm.pl -rf
|
||||
EXE=.exe
|
||||
OBJ=.obj
|
||||
|
||||
# Include files
|
||||
HOST_INCLUDES = -I. -I.. $(USR_INCLUDES) -I$(INSTALL_INCLUDE) -I$(EPICS_BASE_INCLUDE) \
|
||||
-I$(EPICS_BASE_INCLUDE)/os/$(ARCH_CLASS)
|
||||
HOST_INCLUDES = -I. -I.. $(USR_INCLUDES) -I$(INSTALL_INCLUDE) \
|
||||
-I$(EPICS_BASE_INCLUDE) -I$(EPICS_BASE_INCLUDE)/os/$(ARCH_CLASS)
|
||||
|
||||
# Operating system flags (from win32.mak)
|
||||
#
|
||||
@@ -61,31 +76,27 @@ HOST_INCLUDES = -I. -I.. $(USR_INCLUDES) -I$(INSTALL_INCLUDE) -I$(EPICS_BASE_INC
|
||||
#
|
||||
# -MDd : use MSVCRTD (run-time as DLL, multi-thread support)
|
||||
# this also calls for _DLL
|
||||
# -Zi : included debugging info
|
||||
#
|
||||
OP_SYS_FLAGS:=-MDd -Zi -VMG -VMV -DWIN32 -D_WIN32 -D_DEBUG -D_WINDOWS \
|
||||
OP_SYS_FLAGS:=-MDd $(CXX_OPT_FLAGS) -VMG -VMV -DWIN32 -D_WIN32 -D_DEBUG -D_WINDOWS \
|
||||
-D_X86_ -D_NTSDK -D_DLL -D__STDC__=0
|
||||
|
||||
|
||||
HOST_LDLIBS:=user32.lib kernel32.lib wsock32.lib advapi32.lib winmm.lib
|
||||
HOST_LDFLAGS:=-nologo -libpath:$(EPICS_BASE_LIB)
|
||||
|
||||
# Files and flags needed to link DLLs (used in RULES.Host)
|
||||
#
|
||||
# Strange but seems to work without: WIN32LDFLAGS should contain
|
||||
# Strange but seems to work without: WIN32_DLLFLAGS should contain
|
||||
# an entry point:
|
||||
# '-entry:_DllMainCRTStartup$(DLLENTRY)'
|
||||
DLLENTRY:=@12
|
||||
WIN32SYSTEMLIBS := user32.lib kernel32.lib wsock32.lib advapi32.lib winmm.lib
|
||||
|
||||
# yes, for MS it's I386 for 386, 486, Pentium!
|
||||
# don't mix this with VxWorks which has different BSPs for [34]86 !
|
||||
WIN32LDFLAGS := $(WIN32SYSTEMLIBS) -nologo -subsystem:windows -dll\
|
||||
-incremental:no -debug -machine:I386
|
||||
WIN32_DLLFLAGS:=$(HOST_LDFLAGS) $(HOST_LDLIBS)\
|
||||
-subsystem:windows -dll -incremental:no $(LINK_OPT_FLAGS) -machine:I386
|
||||
|
||||
#
|
||||
# The remaining lines are very similar to
|
||||
# all other CONFIG.xxx files.
|
||||
# This includes the GCC lines which may be removed?
|
||||
#
|
||||
|
||||
HOST_LDLIBS:=$(WIN32SYSTEMLIBS)
|
||||
ARCH_DEP_CFLAGS =
|
||||
ARCH_DEP_CXXFLAGS = $(ARCH_DEP_CFLAGS)
|
||||
HOST_CFLAGS = $(HOST_SFLAGS) $(HOST_INCLUDES) $(OP_SYS_FLAGS)
|
||||
@@ -104,10 +115,10 @@ CFLAGS = $(HOST_OPT_FLAGS) $(TARGET_CFLAGS) $(USR_CFLAGS) $(ARCH_DEP_CFLAGS) $(H
|
||||
CXXFLAGS = $(HOST_OPT_FLAGS) $(TARGET_CXXFLAGS) $(USR_CXXFLAGS) $(ARCH_DEP_CXXFLAGS) $(HOST_CXXFLAGS)
|
||||
CPPFLAGS += $(TARGET_CPPFLAGS) $(USR_CPPFLAGS)
|
||||
|
||||
CXX = cl
|
||||
CXX=cl -nologo
|
||||
|
||||
LDFLAGS = $(SPECIAL_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(ARCH_DEP_LDFLAGS) $(HOST_LDFLAGS)
|
||||
LDLIBS = $(TARGET_LDLIBS) $(USR_LDLIBS) $(ARCH_DEP_LDLIBS) $(HOST_LDLIBS)
|
||||
LDFLAGS=$(SPECIAL_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(ARCH_DEP_LDFLAGS) $(HOST_LDFLAGS)
|
||||
LDLIBS=$(TARGET_LDLIBS) $(USR_LDLIBS) $(ARCH_DEP_LDLIBS) $(HOST_LDLIBS)
|
||||
|
||||
# Override SUN defaults
|
||||
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
|
||||
@@ -115,11 +126,10 @@ COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
|
||||
# Problem: MS Visual C++ does not recognize *.cc as C++ source,
|
||||
# we have to compile xx.cc using the flag -Tp xx.cc,
|
||||
# i.e. -Tp has to be immediately before the source file name
|
||||
|
||||
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -DEXPL_TEMPL -c -Tp
|
||||
|
||||
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -Fe$@
|
||||
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -Fe$@
|
||||
LINK.c=link $(LINK_OPT_FLAGS) $(LDFLAGS) -out:$@
|
||||
LINK.cc=$(LINK.c)
|
||||
|
||||
# The DEPENDS_RULE may be a script on other systems,
|
||||
# if you need different rules for .c and .cc,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# CONFIG.Unix.alpha
|
||||
# CONFIG.alpha
|
||||
#
|
||||
# This file is maintained by the EPICS community.
|
||||
|
||||
@@ -24,7 +24,7 @@ RANLIB = ranlib
|
||||
YACC = $(EYACC)
|
||||
LEX = $(ELEX)
|
||||
G++ = g++
|
||||
CCC = cc
|
||||
CCC = cxx
|
||||
|
||||
CP=cp
|
||||
MV = mv
|
||||
@@ -136,7 +136,7 @@ COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
|
||||
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||
# Unlike the 'Unix' makesystem, output flags -o .. are now part of LINK.c[c]
|
||||
LINK.c = $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
LINK.cc = $(CXX) -o $@ $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
LINK.cc = $(CCC) -o $@ $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
|
||||
DEPEND_RULE.c = @echo no DEPENDS_RULE.c defined in CONFIG.alpha
|
||||
DEPEND_RULE.cc = @echo no DEPENDS_RULE.cc defined in CONFIG.alpha
|
||||
|
||||
138
config/CONFIG.cygwin32
Executable file
138
config/CONFIG.cygwin32
Executable file
@@ -0,0 +1,138 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This file is maintained by the EPICS community.
|
||||
|
||||
BUILD_TYPE = Host
|
||||
|
||||
ARCH_CLASS = cygwin32
|
||||
|
||||
GCC = gcc
|
||||
G++ = g++
|
||||
|
||||
#==========================
|
||||
# Fix for cygwin32 beta17.1 includes
|
||||
CXX_INCLUDES = /usr/local/include/g++
|
||||
#==========================
|
||||
|
||||
# Override values in CONFIG_SITE
|
||||
ANSI=GCC
|
||||
STANDARD=GCC
|
||||
CPLUSPLUS=G++
|
||||
|
||||
EXE=.exe
|
||||
|
||||
OBJ=.o
|
||||
|
||||
AR = ar
|
||||
_AR = $(AR) $(ARFLAGS)
|
||||
G++_AR = $(_AR)
|
||||
ARCMD = $($(CPLUSPLUS)_AR)
|
||||
|
||||
RANLIB = ranlib
|
||||
YACC = $(EYACC)
|
||||
LEX = $(ELEX)
|
||||
RMDIR = rm -rf
|
||||
MKDIR = mkdir
|
||||
CP=cp
|
||||
MV=mv
|
||||
RM=rm -f
|
||||
CHMOD = xxxx
|
||||
WHAT = echo
|
||||
|
||||
GCC_ANSI_INVOKE_W_NO = $(GCC) -ansi -w
|
||||
GCC_ANSI_INVOKE_W_YES = $(GCC) -ansi
|
||||
GCC_STRICT_INVOKE_W_YES = $(GCC) -ansi -Wall -pedantic
|
||||
GCC_TRAD_INVOKE_W_NO = $(GCC) -traditional -w
|
||||
GCC_TRAD_INVOKE_W_YES = $(GCC) -traditional
|
||||
GCC_LD_LIBS =
|
||||
GCC_LD_FLAGS =
|
||||
|
||||
C_OLD = $($(STANDARD)_TRAD_INVOKE_W_$(UNIX_WARN))
|
||||
C_ANSI = $($(ANSI)_ANSI_INVOKE_W_$(UNIX_WARN))
|
||||
C_STRICT = $($(ANSI)_STRICT_INVOKE_W_YES)
|
||||
CC = $(C_$(CMPLR))
|
||||
|
||||
LD_LIBS_OLD = $($(STANDARD)_LD_LIBS)
|
||||
LD_LIBS_ANSI = $($(ANSI)_LD_LIBS)
|
||||
LD_LIBS_STRICT = $($(ANSI)_LD_LIBS)
|
||||
CCOMPILER_LDLIBS = $(LD_LIBS_$(CMPLR))
|
||||
LD_FLAGS_OLD = $($(STANDARD)_LD_FLAGS)
|
||||
LD_FLAGS_ANSI = $($(ANSI)_LD_FLAGS)
|
||||
LD_FLAGS_STRICT = $($(ANSI)_LD_FLAGS)
|
||||
CCOMPILER_LDFLAGS = $(LD_FLAGS_$(CMPLR))
|
||||
|
||||
G++_NORMAL_INVOKE_W_NO = $(G++) -ansi -pedantic -w
|
||||
G++_NORMAL_INVOKE_W_YES = $(G++) -ansi -pedantic -Wall
|
||||
G++_STRICT_INVOKE_W_YES = $(G++) -ansi -pedantic -Wtraditional -Wall \
|
||||
-Wmissing-prototypes -Woverloaded-virtual \
|
||||
-Wwrite-strings -Wconversion -Wstrict-prototypes\
|
||||
-Wpointer-arith -Winline
|
||||
|
||||
CXX_NORMAL = $($(CPLUSPLUS)_NORMAL_INVOKE_W_$(UNIX_WARN))
|
||||
CXX_STRICT = $($(CPLUSPLUS)_STRICT_INVOKE_W_YES)
|
||||
|
||||
# GNU make likes CXX
|
||||
CXX = $(CXX_$(CXXCMPLR))
|
||||
|
||||
# Static Build options
|
||||
GCC_SFLAGS_YES= -static
|
||||
GCC_SFLAGS_NO=
|
||||
|
||||
SF_OLD = $($(STANDARD)_SFLAGS_$(STATIC_BUILD))
|
||||
SF_ANSI = $($(ANSI)_SFLAGS_$(STATIC_BUILD))
|
||||
SF_STRICT = $(SF_ANSI)
|
||||
UNIX_SFLAGS = $(SF_$(CMPLR))
|
||||
|
||||
SL_OLD = $($(STANDARD)_SLIBS_$(STATIC_BUILD))
|
||||
SL_ANSI = $($(ANSI)_SLIBS_$(STATIC_BUILD))
|
||||
SL_STRICT = $(SL_ANSI)
|
||||
UNIX_SLIBS = $(SL_$(CMPLR))
|
||||
|
||||
# Optimization
|
||||
OPTIM_YES = -O
|
||||
OPTIM_NO =
|
||||
UNIX_OPT_FLAGS = $(OPTIM_$(UNIX_OPT))
|
||||
|
||||
# Include files
|
||||
UNIX_INCLUDES = -I. -I.. $(USR_INCLUDES) -I$(INSTALL_INCLUDE) -I$(EPICS_BASE_INCLUDE) \
|
||||
-I$(EPICS_BASE_INCLUDE)/os/$(T_A)
|
||||
|
||||
# Operating system flags
|
||||
OP_SYS_FLAGS = -DUNIX
|
||||
|
||||
UNIX_LDFLAGS = -L$(EPICS_BASE_LIB) $(CCOMPILER_LDFLAGS)
|
||||
UNIX_LDLIBS = $(UNIX_SLIBS) -lm $(CCOMPILER_LDLIBS)
|
||||
|
||||
# Architecture specific build flags
|
||||
ARCH_DEP_CFLAGS = -DCYGWIN32
|
||||
ARCH_DEP_CXXFLAGS = $(ARCH_DEP_CFLAGS) -I$(CXX_INCLUDES)
|
||||
#ARCH_DEP_LDLIBS = -lsocket -lnsl
|
||||
# -lsocket needed by libca.a
|
||||
# -lnsl needed by libca.a
|
||||
|
||||
UNIX_CFLAGS = $(UNIX_SFLAGS) $(UNIX_INCLUDES) $(OP_SYS_FLAGS)
|
||||
|
||||
UNIX_CXXFLAGS = $(UNIX_CFLAGS)
|
||||
|
||||
# Target specific flags
|
||||
TARGET_CFLAGS = $($(basename $@)_CFLAGS)
|
||||
TARGET_CXXFLAGS = $($(basename $@)_CXXFLAGS)
|
||||
TARGET_CPPFLAGS = $($(basename $@)_CPPFLAGS)
|
||||
TARGET_LDFLAGS = $($(basename $@)_LDFLAGS)
|
||||
TARGET_LDLIBS = $($(basename $@)_LDLIBS)
|
||||
TARGET_SNCFLAGS = $($(basename $@)_SNCFLAGS)
|
||||
|
||||
CFLAGS = $(UNIX_OPT_FLAGS) $(TARGET_CFLAGS) $(USR_CFLAGS) $(ARCH_DEP_CFLAGS) $(UNIX_CFLAGS)
|
||||
CXXFLAGS = $(UNIX_OPT_FLAGS) $(TARGET_CXXFLAGS) $(USR_CXXFLAGS) $(ARCH_DEP_CXXFLAGS) $(UNIX_CXXFLAGS)
|
||||
CPPFLAGS += $(TARGET_CPPFLAGS) $(USR_CPPFLAGS)
|
||||
|
||||
LDFLAGS = $(SPECIAL_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(ARCH_DEP_LDFLAGS) $(UNIX_LDFLAGS)
|
||||
LDLIBS = $(TARGET_LDLIBS) $(USR_LDLIBS) $(ARCH_DEP_LDLIBS) $(UNIX_LDLIBS)
|
||||
|
||||
LINK.c = $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
LINK.cc = $(CXX) -o $@ $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
|
||||
#DEPENDS_RULE.c = -$(COMPILE.c) -xM $(SRCS.c) > .DEPENDS
|
||||
#DEPENDS_RULE.cc = @echo no DEPENDS_RULE.cc defined in CONFIG.cygwin32
|
||||
DEPENDS_RULE = -$(COMPILE.c) -MM $(SRCS.c) $(SRCS.cc) > .DEPENDS
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
# BUILD_TYPE
|
||||
# Currently either Vx or Unix
|
||||
BUILD_TYPE = Unix
|
||||
BUILD_TYPE = Host
|
||||
|
||||
ARCH_CLASS = hp700
|
||||
|
||||
# Compiler and utility invocation (supply path to compiler here)
|
||||
# (with warning flags built in)
|
||||
@@ -16,17 +18,24 @@ HPCC = cc -Ac
|
||||
TRADCC = cc
|
||||
AR = ar
|
||||
ARCMD = $(AR) $(ARFLAGS)
|
||||
|
||||
RANLIB = ranlib
|
||||
YACC = $(EYACC)
|
||||
LEX = $(ELEX)
|
||||
G++ = g++
|
||||
CCC = CC
|
||||
|
||||
CP = cp
|
||||
MV = mv
|
||||
RM=rm -f
|
||||
RMDIR = rm -rf
|
||||
MKDIR = mkdir
|
||||
CHMOD = "/bin/chmod"
|
||||
WHAT = what
|
||||
|
||||
EXE=
|
||||
OBJ=.o
|
||||
|
||||
ACC_ANSI_INVOKE_W_NO = $(ACC) -w
|
||||
ACC_ANSI_INVOKE_W_YES = $(ACC)
|
||||
ACC_TRAD_INVOKE_W_NO = $(TRADCC) -w
|
||||
@@ -128,8 +137,8 @@ LDLIBS = $(TARGET_LDLIBS) $(USR_LDLIBS) $(ARCH_DEP_LDLIBS) $(UNIX_LDLIBS)
|
||||
# Override defaults
|
||||
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
|
||||
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
LINK.c = $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
LINK.cc = $(CXX) -o $@ $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
DEPENDS_RULE.c = @echo no DEPENDS_RULE.c defined in CONFIG.hp700
|
||||
DEPENDS_RULE.cc = @echo no DEPENDS_RULE.cc defined in CONFIG.hp700
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
SHELL=knts
|
||||
<<<<<<< CONFIG.pc486
|
||||
#
|
||||
# no longer required
|
||||
#
|
||||
#SHELL=knts
|
||||
=======
|
||||
>>>>>>> 1.3
|
||||
|
||||
# BUILD_TYPE
|
||||
# Currently either Vx or Unix
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# $Id$: CONFIG.Unix.solaris,v $
|
||||
# $Id$
|
||||
#
|
||||
# This file is maintained by the EPICS community.
|
||||
|
||||
@@ -42,7 +42,6 @@ WHAT = what
|
||||
EXE=
|
||||
OBJ=.o
|
||||
|
||||
|
||||
ACC_ANSI_INVOKE_W_NO = $(ACC) -Xa -w
|
||||
ACC_ANSI_INVOKE_W_YES = $(ACC) -Xa
|
||||
ACC_STRICT_INVOKE_W_YES = $(ACC) -Xc -v
|
||||
@@ -132,7 +131,7 @@ UNIX_LDFLAGS = -L$(EPICS_BASE_LIB) $(CCOMPILER_LDFLAGS)
|
||||
UNIX_LDLIBS = $(UNIX_SLIBS) -lm $(CCOMPILER_LDLIBS)
|
||||
|
||||
# Architecture specific build flags
|
||||
ARCH_DEP_CFLAGS = -DSOLARIS -D_REENTRANT
|
||||
ARCH_DEP_CFLAGS = -DSOLARIS
|
||||
ARCH_DEP_CXXFLAGS = $(ARCH_DEP_CFLAGS)
|
||||
ARCH_DEP_LDLIBS = -lsocket -lnsl
|
||||
# -lsocket needed by libca.a
|
||||
|
||||
@@ -8,29 +8,34 @@
|
||||
# for c++ build add the dirs gdd and cas after ca
|
||||
# (and uncomment the c++ files in src/lbCom/Makefile.Unix)
|
||||
#
|
||||
DIRS = \
|
||||
tools \
|
||||
include \
|
||||
cxxTemplates \
|
||||
toolsComm\
|
||||
libCom \
|
||||
libvxWorks\
|
||||
cvtDctsdr \
|
||||
dbStatic \
|
||||
db \
|
||||
bpt \
|
||||
ca \
|
||||
util \
|
||||
misc \
|
||||
sequencer \
|
||||
dbtools \
|
||||
rsrv\
|
||||
rec\
|
||||
as \
|
||||
drv\
|
||||
dev\
|
||||
devOpt\
|
||||
iocCore
|
||||
DIRS = tools
|
||||
DIRS += include
|
||||
DIRS += cxxTemplates
|
||||
DIRS += toolsComm
|
||||
DIRS += libCom
|
||||
DIRS += libvxWorks
|
||||
DIRS += cvtDctsdr
|
||||
DIRS += dbStatic
|
||||
DIRS += db
|
||||
DIRS += bpt
|
||||
DIRS += ca
|
||||
DIRS += util
|
||||
DIRS += misc
|
||||
DIRS += sequencer
|
||||
DIRS += dbtools
|
||||
DIRS += rsrv
|
||||
DIRS += rec
|
||||
DIRS += as
|
||||
DIRS += drv
|
||||
DIRS += dev
|
||||
DIRS += devOpt
|
||||
DIRS += iocCore
|
||||
|
||||
#
|
||||
# if CPLUSPLUS isnt empty then include C++ src codes
|
||||
#
|
||||
DIRS += $(patsubst %,gdd,$(strip $(CPLUSPLUS)))
|
||||
DIRS += $(patsubst %,cas,$(strip $(CPLUSPLUS)))
|
||||
|
||||
EPICS_BASE = $(TOP)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ EPICS_VERSION=3
|
||||
EPICS_REVISION=13
|
||||
EPICS_MODIFICATION=0
|
||||
EPICS_UPDATE_NAME=beta
|
||||
EPICS_UPDATE_LEVEL=8
|
||||
EPICS_UPDATE_LEVEL=10
|
||||
|
||||
EPICS_VERSION_STRING="EPICS Version ${EPICS_VERSION}.${EPICS_REVISION}.${EPICS_MODIFICATION}.${EPICS_UPDATE_NAME}${EPICS_UPDATE_LEVEL}"
|
||||
|
||||
|
||||
@@ -42,8 +42,12 @@ DIVIDER = .
|
||||
EYACC = $(EPICS_BASE)/bin/$(HOST_ARCH)/antelope$(EXE)
|
||||
ELEX = $(EPICS_BASE)/bin/$(HOST_ARCH)/e_flex$(EXE) -S$(EPICS_BASE_INCLUDE)/flex.skel.static
|
||||
|
||||
# Default for perl if it's on the PATH,
|
||||
# otherwise override this in e.g. CONFIG_SITE
|
||||
PERL=perl
|
||||
|
||||
# install from EPICS
|
||||
INSTALL = $(EPICS_BASE)/bin/$(HOST_ARCH)/installEpics
|
||||
INSTALL = $(PERL) $(EPICS_BASE)/bin/$(HOST_ARCH)/installEpics.pl
|
||||
INSTALL_PRODUCT = $(INSTALL)
|
||||
|
||||
# dbtools from EPICS
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
# not allowed around the '=' signs or in unquoted values.
|
||||
# Makefile variables are not defined here.
|
||||
#
|
||||
# Note: This file is read by base/src/libCom/bldEnvdata.pl,
|
||||
# so the variable definitions in here should be kept 'simple':
|
||||
# VAR=VALUE
|
||||
# each one on a single line.
|
||||
#
|
||||
|
||||
|
||||
@@ -59,10 +63,11 @@ EPICS_CAS_SERVER_PORT=
|
||||
|
||||
|
||||
# Log Server:
|
||||
# EPICS_IOC_LOG_PORT Log server port number.
|
||||
|
||||
# EPICS_IOC_LOG_PORT Log server port number etc.
|
||||
EPICS_IOC_LOG_PORT=7004
|
||||
|
||||
#EPICS_IOC_LOG_INET=""
|
||||
#EPICS_IOC_LOG_FILE_LIMIT=100000
|
||||
#EPICS_IOC_LOG_FILE_NAME=/a/b/c/d/iocs.log
|
||||
|
||||
# Other services:
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ endif
|
||||
# niCpu030
|
||||
# pc486
|
||||
#
|
||||
CROSS_COMPILER_TARGET_ARCHS=mv167 mv162
|
||||
CROSS_COMPILER_TARGET_ARCHS=mv167
|
||||
|
||||
# If only a subset of the host architectures perform
|
||||
# the build for the CROSS_COMPILER_TARGET_ARCHS
|
||||
@@ -47,16 +47,17 @@ CROSS_COMPILER_TARGET_ARCHS=mv167 mv162
|
||||
#CROSS_COMPILER_HOST_ARCHS=sun4
|
||||
|
||||
# VxWorks directory
|
||||
#VX_DIR=/usr/csite/vw/5.1.1/vw
|
||||
#VX_DIR=$(VW)
|
||||
#VX_DIR=/usr/local/vw/vxV51.mm
|
||||
#VX_DIR=/usr/local/vw/vxV52/vw
|
||||
VX_DIR=/usr/local/vw/vxV52p1/vw
|
||||
|
||||
# Gnu directory for gcc
|
||||
#VX_GNU = $(VX_DIR)
|
||||
#VX_GNU = $(VX_GNU)
|
||||
VX_GNU = $(VX_DIR)/../vxgccV2.2.3.1
|
||||
|
||||
# Gnu directory for g++
|
||||
#GNU_DIR = $(LOCAL_GNU)
|
||||
GNU_DIR = /usr/local/hideos/gnu_install-2.7.2
|
||||
GNU_BIN = $(GNU_DIR)/bin
|
||||
GNU_LIB = $(GNU_DIR)/lib
|
||||
@@ -76,10 +77,12 @@ ANSI=ACC
|
||||
#STANDARD=HPCC
|
||||
STANDARD=ACC
|
||||
|
||||
# Client C++ Compiler (Not supported yet)
|
||||
# C++ Compiler
|
||||
# G++ (g++) GNU C++
|
||||
# CCC (CC) SUN C++
|
||||
# CCC (CC) OS VENDOR C++
|
||||
#CPLUSPLUS=G++
|
||||
#Note: if CPLUSPLUS is empty then C++ src codes are not built
|
||||
#CPLUSPLUS= # use this if site does not have C++ compiler
|
||||
CPLUSPLUS=CCC
|
||||
|
||||
# Build client objects statically ?
|
||||
|
||||
29
config/CONFIG_SITE.Vx.68k.cygwin32
Normal file
29
config/CONFIG_SITE.Vx.68k.cygwin32
Normal file
@@ -0,0 +1,29 @@
|
||||
# $Id$
|
||||
#
|
||||
# This file is maintained by the EPICS community.
|
||||
|
||||
|
||||
# Site host architecture specific overrides for Vx.68k
|
||||
#
|
||||
|
||||
ANSI=GCC
|
||||
STANDARD=GCC
|
||||
CPLUSPLUS=G++
|
||||
|
||||
VX_DIR=/vw/vxV52p1/vw
|
||||
VX_GNU=/usr/local
|
||||
|
||||
VX_GNU_BIN = $(VX_GNU)/bin
|
||||
VX_GNU_LIB = $(VX_GNU)/lib
|
||||
|
||||
AR=$(VX_GNU_BIN)/m68k-wrs-vxworks-ar.exe
|
||||
RANLIB=$(VX_GNU_BIN)/m68k-wrs-vxworks-ranlib.exe
|
||||
CC=$(VX_GNU_BIN)/m68k-wrs-vxworks-gcc.exe -B$(VX_GNU_LIB)/gcc-lib/ -nostdinc
|
||||
G++=$(VX_GNU_BIN)/m68k-wrs-vxworks-g++.exe -B$(VX_GNU_LIB)/gcc-lib/ -nostdinc
|
||||
CPP=$(VX_GNU_BIN)/m68k-wrs-vxworks-cpp.exe -nostdinc
|
||||
LD=$(VX_GNU_BIN)/m68k-wrs-vxworks-ld.exe -r
|
||||
|
||||
# Not in cygwin32
|
||||
WHAT = echo
|
||||
|
||||
|
||||
21
config/CONFIG_SITE.cygwin32
Executable file
21
config/CONFIG_SITE.cygwin32
Executable file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Site Specific Configuration Information
|
||||
# Only the local epics system manager should modify this file
|
||||
|
||||
|
||||
# Default compiler, individual Makefiles will override
|
||||
# if they cannot support ANSI compilation.
|
||||
# STRICT - ANSI C - force warning flags
|
||||
# ANSI - ANSI C
|
||||
# OLD - Standard C - Not appropriate here.
|
||||
CMPLR=ANSI
|
||||
|
||||
# Default C++ compiler, individual Makefiles will override
|
||||
# if they are coded to a higher standard.
|
||||
# STRICT - ANSI C++ force strict warning flags
|
||||
# NORMAL - ANSI C++ optional warning flags
|
||||
CXXCMPLR=NORMAL
|
||||
|
||||
SPECIAL_LANG = .
|
||||
@@ -10,6 +10,11 @@
|
||||
# not allowed around the '=' signs or in unquoted values.
|
||||
# Makefile variables are not defined here.
|
||||
#
|
||||
# Note: This file is read by base/src/libCom/bldEnvdata.pl,
|
||||
# so the variable definitions in here should be kept 'simple':
|
||||
# VAR=VALUE
|
||||
# each one on a single line.
|
||||
#
|
||||
|
||||
# Site-specific environment settings
|
||||
|
||||
|
||||
@@ -49,16 +49,22 @@ A) In CONFIG.<WIN32, sun4, hp700, ... whatever you are using>:
|
||||
|
||||
3) Make sure that the following (new) macros are defined:
|
||||
|
||||
CP =$(PERL) $(EPICS_BASE)/src/tools/cp.pl
|
||||
MV =$(PERL) $(EPICS_BASE)/src/tools/mv.pl
|
||||
RM =$(PERL) $(EPICS_BASE)/src/tools/rm.pl -f
|
||||
MKDIR=$(PERL) $(EPICS_BASE)/src/tools/mkdir.pl
|
||||
RMDIR=$(PERL) $(EPICS_BASE)/src/tools/rm.pl -rf
|
||||
or
|
||||
CP=cp
|
||||
MV=mv
|
||||
RM=rm -f
|
||||
MKDIR=mkdir
|
||||
RMDIR=rm -rf
|
||||
|
||||
EXE=
|
||||
OBJ=.o
|
||||
|
||||
4) LINK.c and LINK.cc must now include the target-flag, e.g.:
|
||||
|
||||
LINK.c = $(CC) $(LDFLAGS) -o $@
|
||||
|
||||
because the "-o $@" is also system dependent (it's -Fe$@ for WIN32)
|
||||
|
||||
@@ -11,40 +11,14 @@ CONFIGS += CONFIG_BASE_VERSION
|
||||
CONFIGS += CONFIG_COMMON
|
||||
CONFIGS += CONFIG_ENV
|
||||
|
||||
CONFIGS += CONFIG.WIN32
|
||||
CONFIGS += CONFIG.pc486
|
||||
CONFIGS += CONFIG.Linux
|
||||
CONFIGS += CONFIG.alpha
|
||||
CONFIGS += CONFIG.hp700
|
||||
CONFIGS += CONFIG.sgi
|
||||
CONFIGS += CONFIG.solaris
|
||||
CONFIGS += CONFIG.sun4
|
||||
CONFIGS += CONFIG.hkv2f
|
||||
CONFIGS += CONFIG.mv147
|
||||
CONFIGS += CONFIG.mv162
|
||||
CONFIGS += CONFIG.mv162lc
|
||||
CONFIGS += CONFIG.mv167
|
||||
CONFIGS += CONFIG.niCpu030
|
||||
CONFIGS += $(BUILD_ARCHS:%=CONFIG.%)
|
||||
|
||||
CONFIGS += CONFIG.Vx.68k
|
||||
|
||||
CONFIGS += CONFIG_SITE
|
||||
CONFIGS += CONFIG_SITE_ENV
|
||||
|
||||
CONFIGS += CONFIG_SITE.WIN32
|
||||
CONFIGS += CONFIG_SITE.pc486
|
||||
CONFIGS += CONFIG_SITE.Linux
|
||||
CONFIGS += CONFIG_SITE.alpha
|
||||
CONFIGS += CONFIG_SITE.hp700
|
||||
CONFIGS += CONFIG_SITE.sgi
|
||||
CONFIGS += CONFIG_SITE.solaris
|
||||
CONFIGS += CONFIG_SITE.sun4
|
||||
CONFIGS += CONFIG_SITE.hkv2f
|
||||
CONFIGS += CONFIG_SITE.mv147
|
||||
CONFIGS += CONFIG_SITE.mv162lc
|
||||
CONFIGS += CONFIG_SITE.mv162
|
||||
CONFIGS += CONFIG_SITE.mv167
|
||||
CONFIGS += CONFIG_SITE.niCpu030
|
||||
CONFIGS += $(BUILD_ARCHS:%=CONFIG_SITE.%)
|
||||
|
||||
CONFIGS += RULES.Host
|
||||
CONFIGS += RULES.Vx
|
||||
|
||||
@@ -13,14 +13,13 @@ buildInstall: .DEPENDS dbd $(DBFROMTEMPLATE) $(INDDBFROMTEMPLATE) $(PROD)
|
||||
|
||||
inc build depends:
|
||||
|
||||
dbd:
|
||||
@if [ ! -d $(TOP)/dbd ]; then \
|
||||
mkdir $(TOP)/dbd ; \
|
||||
fi
|
||||
@if [ ! -d dbd ]; then \
|
||||
echo "ln -s $(TOP)/dbd dbd" ; \
|
||||
ln -s $(TOP)/dbd dbd ; \
|
||||
fi
|
||||
$(TOP)/dbd:
|
||||
$(MKDIR) $(TOP)/dbd
|
||||
|
||||
dbd: $(TOP)/dbd
|
||||
ifndef WIN32
|
||||
ln -s $(TOP)/dbd dbd
|
||||
endif
|
||||
|
||||
|
||||
$(DBFROMTEMPLATE):%.db: %.template %.substitutions
|
||||
@@ -30,16 +29,20 @@ $(DBFROMTEMPLATE):%.db: %.template %.substitutions
|
||||
|
||||
$(INDDBFROMTEMPLATE):%.db: %.substitutions
|
||||
$(RM) $@
|
||||
ifndef WIN32
|
||||
$(SUBTOOL) $(PREFIX).template $*.substitutions > $@
|
||||
endif
|
||||
|
||||
.DEPENDS: Makefile
|
||||
@$(RM) $@
|
||||
ifndef WIN32
|
||||
@for NAME in $(INDDBFROMTEMPLATE) garbage_marty ; do \
|
||||
if [ $$NAME != garbage_marty ] ; then \
|
||||
PREFIX="`echo $$NAME | sed -e 's-[0-9]--g' | sed -e 's-\.db--g'`";\
|
||||
echo "$$NAME: $$PREFIX.template" >> $@;\
|
||||
fi ; \
|
||||
done
|
||||
endif
|
||||
|
||||
clean::
|
||||
@$(RM) dbd $(DBFROMTEMPLATE) $(INDDBFROMTEMPLATE) .DEPENDS $(PROD)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Rules for making things specified in Makefile.Host
|
||||
@@ -52,7 +53,8 @@ vpath %.h $(USER_VPATH)
|
||||
# USR_CXXFLAGS C++ flags
|
||||
# INC include-files to install
|
||||
# LIBSRCS source files for building library
|
||||
# PROD_LIBS libs needed by PROD
|
||||
# PROD_LIBS EPICS libs needed by PROD and TESTPROD
|
||||
# SYS_PROD_LIBS system libs needed by PROD and TESTPROD
|
||||
# PROD products to build and install
|
||||
# SCRIPTS scripts to install
|
||||
#
|
||||
@@ -126,6 +128,20 @@ endif
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# concat specific library contents (if defined) to SYS_PROD_LIBS
|
||||
#
|
||||
ifneq (x$(SYS_PROD_LIBS_$(ARCH_CLASS)),x)
|
||||
SYS_PROD_LIBS += $(subst -nil-,,$(SYS_PROD_LIBS_$(ARCH_CLASS)))
|
||||
|
||||
else
|
||||
|
||||
ifdef SYS_PROD_LIBS_DEFAULT
|
||||
SYS_PROD_LIBS += $(SYS_PROD_LIBS_DEFAULT)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# concat specific products
|
||||
#
|
||||
@@ -179,7 +195,7 @@ ifeq ($(LIBTYPE),SHARED)
|
||||
# create name for dll, import file
|
||||
DLLNAME:=$(LIBRARY).dll
|
||||
# libs defined that we need to link the DLL with?
|
||||
DLL_DEP_LIBS:=$(DLL_LIBS:%=$(INSTALL_LIB)/%.lib)
|
||||
DLL_DEP_LIBS:=$(DLL_LIBS:%=%.lib)
|
||||
endif # LIBTYPE=SHARED
|
||||
endif # WIN32
|
||||
|
||||
@@ -189,22 +205,39 @@ endif # LIBRARY and LIBOBJS
|
||||
# dito for libraries used by PROD
|
||||
#
|
||||
ifdef PROD_LIBS
|
||||
# add to USR_LDLIBS so that the libs are linked
|
||||
|
||||
ifdef WIN32
|
||||
PRODDEPLIBS:=$(PROD_LIBS:%=$(INSTALL_LIB)/%.lib)
|
||||
# add to USR_LDLIBS so that the libs are linked
|
||||
# we need the full path because there is no "-L" option on WIN32....
|
||||
USR_LDLIBS += $(PRODDEPLIBS)
|
||||
USR_LDLIBS += -libpath:$(INSTALL_LIB) $(PROD_LIBS:%=%.lib)
|
||||
else
|
||||
# On Unix: library "ca" is linked with "-lca" etc.
|
||||
# A library may be just newly build in the local dir: add "-L."
|
||||
PRODDEPLIBS=$(PROD_LIBS:%=lib%.a)
|
||||
USR_LDLIBS += -L. $(PROD_LIBS:%=-l%)
|
||||
PRODDEPLIBS=$(PROD_LIBS:%=$(INSTALL_LIB)/lib%.a)
|
||||
USR_LDLIBS += -L$(INSTALL_LIB) $(PROD_LIBS:%=-l%)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
# dito for system libraries used by PROD
|
||||
#
|
||||
ifdef SYS_PROD_LIBS
|
||||
|
||||
ifdef WIN32
|
||||
# add to USR_LDLIBS so that the libs are linked
|
||||
# we need the full path because there is no "-L" option on WIN32....
|
||||
USR_LDLIBS += $(SYSPRODDEPLIBS)
|
||||
else
|
||||
# On Unix: it is difficult to determine where the
|
||||
# system lib is (because of add on compilere).
|
||||
# Therefore no additions to PRODDEPLIBS for
|
||||
# system libraries.
|
||||
#
|
||||
USR_LDLIBS += $(SYS_PROD_LIBS:%=-l%)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# adjust executables
|
||||
ifdef PROD
|
||||
PROD := $(addsuffix $(EXE), $(PROD))
|
||||
@@ -263,17 +296,6 @@ endif
|
||||
#
|
||||
all:: install
|
||||
|
||||
# Problem on WIN32:
|
||||
# There seems to be no -L switch, so we have to specify the
|
||||
# full library names (including the path).
|
||||
# OK, so we prefix all libs by $(INSTALL_LIB) to be able to link
|
||||
# with the installed libraries. This means, however, that
|
||||
# libs have to be installed _before_ we build any PROD that uses them,
|
||||
# because we cannot use them from the current O.WIN32 directory any more.
|
||||
# Example: dbExpand etc. in dbStatic all need the db library.
|
||||
#
|
||||
# Solution: place INSTALL_DLLS and _LIBS in build
|
||||
#
|
||||
build:: $(LIBNAME) $(DLLNAME) \
|
||||
$(INSTALL_LOCATION_LIB) $(INSTALL_LIB)\
|
||||
$(INSTALL_LIBS) $(INSTALL_DLLS) $(PROD) $(TESTPROD)
|
||||
@@ -311,28 +333,20 @@ clean::
|
||||
$(DIRECTORY_TARGETS) :
|
||||
$(MKDIR) $@
|
||||
|
||||
# Problem: PRODDEPLIBS may contain libm.a etc. which we cannot locate
|
||||
# But: The order in build/install should make sure that libs are
|
||||
# in place before we build PROD anyway.
|
||||
# $(PROD): $(PRODDEPLIBS)
|
||||
|
||||
# The order of the following dependencies is
|
||||
# VERY IMPORTANT !!!!
|
||||
|
||||
# generic rule to build executable from same-name-object:
|
||||
# (this should be handled by the implicit rule below)
|
||||
# If you want to break this on WIN32, please forget
|
||||
# that $(COMPILE.cc) is like $(COMPILE.c) for WIN32
|
||||
# except the first one ends in -Tp to select 'C++'.
|
||||
#
|
||||
#%$(EXE): %$(OBJ)
|
||||
#ifdef WIN32
|
||||
# $(LINK.c) $< $(LDLIBS)
|
||||
#else
|
||||
# $(RM) $@
|
||||
# echo LINKING:
|
||||
# $(LINK.c) $< $(LDLIBS)
|
||||
#endif
|
||||
# EPICS uses .cc for C++, which is not recognized
|
||||
# by MS Visual C++, so -Tp has to be directly in front of
|
||||
# the source file.
|
||||
# -> put the source file directly after $(COMPILE.cc),
|
||||
|
||||
# explicit list of source files given for PROD ?
|
||||
# (otherwise implicit rule .c -> $(OBJ) -> $(EXE)
|
||||
# (otherwise implicit rules .c -> $(EXE), .cc -> $(EXE)
|
||||
ifdef SRCS
|
||||
|
||||
ifeq ($(findstring cc,$(suffix $(SRCS))),cc)
|
||||
@@ -343,11 +357,10 @@ endif
|
||||
|
||||
PROD_OBJS=$(addsuffix $(OBJ), $(basename $(SRCS)))
|
||||
|
||||
$(PROD): $(PROD_OBJS)
|
||||
$(RM) $@
|
||||
echo $(LDLIBS)
|
||||
$(PROD): $(PROD_OBJS) $(PRODDEPLIBS)
|
||||
@$(RM) $@
|
||||
$(PROD_LINKER) $(PROD_OBJS) $(LDLIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
# explicit list of source files given for TESTPROD ?
|
||||
# (otherwise implicit rule .c -> $(OBJ) -> $(EXE)
|
||||
@@ -361,47 +374,58 @@ endif
|
||||
|
||||
TESTPROD_OBJS=$(addsuffix $(OBJ), $(basename $(TESTPROD_SRCS)))
|
||||
|
||||
$(TESTPROD): $(TESTPROD_OBJS)
|
||||
$(RM) $@
|
||||
$(TESTPROD): $(TESTPROD_OBJS) $(PRODDEPLIBS)
|
||||
@$(RM) $@
|
||||
$(TESTPROD_LINKER) $(TESTPROD_OBJS) $(LDLIBS)
|
||||
endif
|
||||
|
||||
%$(EXE): %.c
|
||||
$(RM) $@
|
||||
$(LINK.c) $< $(LDLIBS)
|
||||
# Generic Rules for 'simple' targets that
|
||||
# can be generated from a single source with same basename.
|
||||
#
|
||||
# The usual two rules .c* -> $(OBJ) and then $(OBJ) -> $(EXE)
|
||||
# do not work because the $(OBJ)->$(EXE) rule wouldn't
|
||||
# know if the original source was C or C++.
|
||||
#
|
||||
# Hint: The $(subst...) construct removes the .c or .cc
|
||||
# as well as the '../' from the filename and adds $(OBJ):
|
||||
# e.g. $< = '../abc.c' -> 'abc.o'
|
||||
%$(EXE): %.c $(PRODDEPLIBS)
|
||||
@$(RM) $@
|
||||
$(COMPILE.c) $<
|
||||
$(LINK.c) $(subst ../,,$(basename $<))$(OBJ) $(LDLIBS)
|
||||
|
||||
%$(EXE): %.cc
|
||||
$(RM) $@
|
||||
$(LINK.cc) $< $(LDLIBS)
|
||||
%$(EXE): %.cc $(PRODDEPLIBS)
|
||||
@$(RM) $@
|
||||
$(COMPILE.cc) $<
|
||||
$(LINK.cc) $(subst ../,,$(basename $<))$(OBJ) $(LDLIBS)
|
||||
|
||||
%$(OBJ): %.c
|
||||
$(RM) $@
|
||||
@$(RM) $@
|
||||
$(COMPILE.c) $<
|
||||
|
||||
%$(OBJ): %.cc
|
||||
$(RM) $@
|
||||
@$(RM) $@
|
||||
$(COMPILE.cc) $<
|
||||
|
||||
%.c %.h: ../%.y
|
||||
$(RM) y.tab.c y.tab.h
|
||||
#
|
||||
# rename the y.tab.h file only if we
|
||||
# are creating it
|
||||
#
|
||||
%.h %.c: ../%.y
|
||||
$(RM) $*.c y.tab.c
|
||||
ifeq ($(findstring -d, $(YACCOPT)),-d)
|
||||
$(RM) $*.h y.tab.h
|
||||
endif
|
||||
$(YACC) $(YACCOPT) $<
|
||||
@if [ -f y.tab.c ]; \
|
||||
then \
|
||||
echo "$(MV) y.tab.c $*.c"; \
|
||||
$(RM) $*.c; \
|
||||
$(MV) y.tab.c $*.c; \
|
||||
fi
|
||||
@if [ -f y.tab.h ]; \
|
||||
then \
|
||||
echo "$(MV) y.tab.h $*.h"; \
|
||||
$(RM) $*.h; \
|
||||
$(MV) y.tab.h $*.h; \
|
||||
fi
|
||||
$(MV) y.tab.c $*.c
|
||||
ifeq ($(findstring -d, $(YACCOPT)),-d)
|
||||
$(MV) y.tab.h $*.h
|
||||
endif
|
||||
|
||||
%.c: ../%.l
|
||||
$(RM) lex.yy.c
|
||||
@$(RM) lex.yy.c
|
||||
$(LEX) $(LEXOPT) $<
|
||||
$(RM) $@
|
||||
@$(RM) $@
|
||||
$(MV) lex.yy.c $@
|
||||
|
||||
#state notation language rule
|
||||
@@ -445,7 +469,6 @@ endif
|
||||
$(MANGEN) -s $(<F)
|
||||
$(MV) $(<F).nr $(<F).1
|
||||
|
||||
|
||||
# Rules for building LIBRARY with LIBSRCS
|
||||
# (which are now LIBNAME, LIBOBJS)
|
||||
#
|
||||
@@ -468,7 +491,6 @@ ifeq ($(DLL_DEF_FILE), $(wildcard $(DLL_DEF_FILE)))
|
||||
DLL_DEF := -def:$(DLL_DEF_FILE)
|
||||
endif
|
||||
|
||||
# Ugly trick:
|
||||
# HOST_OPT_FLAGS is part of CFLAGS/CXXFLAGS,
|
||||
# which in turn are used in COMPILE.c[c]
|
||||
#
|
||||
@@ -478,17 +500,16 @@ endif
|
||||
# If so, we define _WINDLL so that
|
||||
# e.g. include/shareLib.h works correctly.
|
||||
#
|
||||
#HOST_OPT_FLAGS += $(subst $@, -D_WINDLL, $(findstring $@,$(LIBOBJS)))
|
||||
HOST_OPT_FLAGS += $(subst $@, -D_WINDLL, $(findstring $@,$(LIBOBJS)))
|
||||
|
||||
$(DLLNAME): $(LIBOBJS)
|
||||
link $(WIN32LDFLAGS)\
|
||||
-implib:$(LIBNAME) -out:$(DLLNAME) $(DLL_DEF) \
|
||||
$(DLL_DEP_LIBS) $(LIBOBJS)
|
||||
link $(WIN32_DLLFLAGS)\
|
||||
-implib:$(LIBNAME) -out:$(DLLNAME) $(DLL_DEF)\
|
||||
$(DLL_DEP_LIBS) $(ARCH_DEP_LDLIBS) $(HOST_LDLIBS) $(LIBOBJS)
|
||||
else
|
||||
# still on WIN32, this time no DLL but plain lib requested:
|
||||
$(LIBNAME): $(LIBOBJS)
|
||||
lib -nologo -verbose -out:$(LIBNAME)\
|
||||
$(LIBOBJS)
|
||||
lib -nologo -verbose -out:$(LIBNAME) $(LIBOBJS)
|
||||
lib -nologo -list $(LIBNAME)
|
||||
|
||||
endif # LIBTYPE is SHARED ?
|
||||
@@ -556,12 +577,10 @@ $(INSTALL_INCLUDE)/%: ../%
|
||||
|
||||
$(INSTALL_DOC)/%: %
|
||||
@echo "Installing doc $@"
|
||||
@testmkdir $(INSTALL_DOC)
|
||||
@$(INSTALL) -m 644 $< $(INSTALL_DOC)
|
||||
|
||||
$(INSTALL_DOC)/%: ../%
|
||||
@echo "Installing doc $@"
|
||||
@testmkdir $(INSTALL_DOC)
|
||||
@$(INSTALL) -m 644 $< $(INSTALL_DOC)
|
||||
|
||||
$(INSTALL_TEMPLATES)/$(TEMPLATES_DIR)/%: ../%
|
||||
|
||||
@@ -51,7 +51,11 @@ buildInstall :: build $(INSTALL_INCREC)\
|
||||
$(INSTALL_DOC) $(INSTALL_DOCS) \
|
||||
$(INSTALL_SCRIPTS) $(INSTALL_INSTALLS)\
|
||||
$(INSTALL_DBD) $(INSTALL_DBS) $(INSTALL_BPTS) \
|
||||
$(INSTALL_DBDNAME) binInstalls
|
||||
$(INSTALL_DBDNAME)
|
||||
|
||||
ifdef BIN_INSTALLS
|
||||
buildInstall :: binInstalls
|
||||
endif
|
||||
|
||||
depends:: $(SRCS.c) $(SRCS.cc)
|
||||
ifdef SRCS
|
||||
@@ -78,7 +82,7 @@ $(DIRECTORY_TARGETS) :
|
||||
|
||||
%: %.o
|
||||
$(RM) $@
|
||||
$(LINK.c) $@ $<
|
||||
$(LINK.c) $@ $< $(LDLIBS)
|
||||
|
||||
#$(PROD): $(OBJS)
|
||||
# $(RM) $@
|
||||
@@ -100,19 +104,20 @@ $(DIRECTORY_TARGETS) :
|
||||
$(RM) $@
|
||||
$(COMPILE.cc) $<
|
||||
|
||||
%.c: ../%.y
|
||||
$(RM) y.tab.c y.tab.h
|
||||
#
|
||||
# rename the y.tab.h file only if we
|
||||
# are creating it
|
||||
#
|
||||
%.h %.c: ../%.y
|
||||
$(RM) $*.c y.tab.c
|
||||
ifeq ($(findstring -d, $(YACCOPT)),-d)
|
||||
$(RM) $*.h y.tab.h
|
||||
endif
|
||||
$(YACC) $(YACCOPT) $<
|
||||
@if [ -f y.tab.c ]; \
|
||||
then \
|
||||
echo "$(MV) y.tab.c $*.c"; \
|
||||
$(MV) y.tab.c $*.c; \
|
||||
fi
|
||||
@if [ -f y.tab.h ]; \
|
||||
then \
|
||||
echo "$(MV) y.tab.h $*.h"; \
|
||||
$(MV) y.tab.h $*.h; \
|
||||
fi
|
||||
$(MV) y.tab.c $*.c
|
||||
ifeq ($(findstring -d, $(YACCOPT)),-d)
|
||||
$(MV) y.tab.h $*.h
|
||||
endif
|
||||
|
||||
%.c: ../%.l
|
||||
$(RM) lex.yy.c
|
||||
@@ -154,7 +159,7 @@ $(DIRECTORY_TARGETS) :
|
||||
$(MV) $(<F).nr $(<F).1
|
||||
|
||||
binInstalls: $(BIN_INSTALLS)
|
||||
@$(INSTALL) -m 555 $^ $(INSTALL_BIN)
|
||||
$(INSTALL) -m 555 $^ $(INSTALL_BIN)
|
||||
|
||||
$(INSTALL_DBD)/%: %
|
||||
@echo "Installing $@"
|
||||
@@ -199,12 +204,12 @@ $(DBDNAME): ../$(DBDEXPAND)
|
||||
$(LIBNAME): $(LIBOBJS)
|
||||
@echo Building library $@
|
||||
@$(RM) $@
|
||||
$(LINK.c) $@ $(LIBOBJS)
|
||||
$(LINK.c) $@ $(LIBOBJS) $(LDLIBS)
|
||||
|
||||
$(LIBNAME_CXX): $(LIBOBJS_CXX)
|
||||
@echo Building CXX library $@
|
||||
@$(RM) $@
|
||||
$(LINK.cc) $@ $(LIBOBJS_CXX)
|
||||
$(LINK.cc) $@ $(LIBOBJS_CXX) $(CXXLDLIBS)
|
||||
|
||||
$(INSTALL_BIN)/%: %
|
||||
@echo "Installing $@"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#RULES.ioc
|
||||
|
||||
ifndef WIN32
|
||||
APPDIR := $(shell grep '.*".*App/' st.* | sed -e 's/.*"\(.*App\).*/\1/' | sort -u )
|
||||
endif
|
||||
|
||||
ASCF = $(TOP)/../ascf
|
||||
TARGETBIN = $(TOP)/bin/$(ARCH)
|
||||
ARCHS = $(BUILD_ARCHS) host cross
|
||||
@@ -15,13 +19,16 @@ buildInstall: makelinks
|
||||
inc build depends:
|
||||
|
||||
makelinks:
|
||||
ifndef WIN32
|
||||
@$(RM) ascf bin vxWorks vxWorks.sym dbd share $(APPDIR)
|
||||
ln -s $(ASCF) ascf
|
||||
ln -s $(TARGETBIN) bin
|
||||
ln -s $(TARGETBIN)/vxWorks vxWorks
|
||||
ln -s $(TARGETBIN)/vxWorks.sym vxWorks.sym
|
||||
ln -s $(TOP)/dbd dbd
|
||||
ifdef SHARE
|
||||
ln -s $(SHARE) share
|
||||
endif
|
||||
@for dir in $(APPDIR) scum ; do \
|
||||
if [ $$dir = scum ]; then \
|
||||
: ; \
|
||||
@@ -35,6 +42,7 @@ makelinks:
|
||||
echo "$$dir not found" ; \
|
||||
fi ; \
|
||||
done
|
||||
endif
|
||||
|
||||
clean::
|
||||
@$(RM) ascf bin vxWorks vxWorks.sym dbd share $(APPDIR)
|
||||
|
||||
@@ -51,15 +51,16 @@ $(crossActionArchTargets) :
|
||||
$(crossArchs) :
|
||||
endif
|
||||
|
||||
$(hostDirs) :
|
||||
$(MKDIR) $@
|
||||
echo "T_A=$(subst O.,,$@)" > $@/Makefile
|
||||
echo "include ../Makefile.$(BUILD_TYPE)" >> $@/Makefile
|
||||
$(hostDirs) : $(EPICS_BASE)/config/makeMakefile.pl
|
||||
$(PERL) $(EPICS_BASE)/config/makeMakefile.pl $@ $(BUILD_TYPE)
|
||||
|
||||
$(crossDirs) :
|
||||
$(MKDIR) $@
|
||||
echo "T_A=$(subst O.,,$@)" > $@/Makefile
|
||||
echo "include ../Makefile.Vx" >> $@/Makefile
|
||||
$(crossDirs) : $(EPICS_BASE)/config/makeMakefile.pl
|
||||
$(PERL) $(EPICS_BASE)/config/makeMakefile.pl $@ Vx
|
||||
|
||||
ifneq ($(EPICS_BASE),$(TOP))
|
||||
$(EPICS_BASE)/config/makeMakefile.pl : $(TOP)/config/makeMakefile.pl
|
||||
$(CP) $(TOP)/config/makeMakefile.pl $(EPICS_BASE)/config/makeMakefile.pl
|
||||
endif
|
||||
|
||||
#
|
||||
# host/cross action targets
|
||||
|
||||
30
config/makeMakefile.pl
Normal file
30
config/makeMakefile.pl
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/local/bin/perl
|
||||
#
|
||||
# makeMakefile.pl
|
||||
#
|
||||
# called from RULES_ARCHS
|
||||
#
|
||||
#
|
||||
# Usage: perl makeMakefile.pl O.*-dir Makefile-Type
|
||||
|
||||
$dir = $ARGV[0];
|
||||
$type= $ARGV[1];
|
||||
$makefile="$dir/Makefile";
|
||||
|
||||
if ($dir =~ m'O.(.+)')
|
||||
{
|
||||
$t_a = $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Cannot extract T_A from $dir";
|
||||
}
|
||||
|
||||
mkdir ($dir, 0777) unless -d $dir;
|
||||
|
||||
open OUT, "> $makefile" or die "Cannot create $makefile";
|
||||
print OUT "T_A=$t_a\n";
|
||||
print OUT "include ../Makefile.$type\n";
|
||||
close OUT;
|
||||
|
||||
# EOF makeMakefile.pl
|
||||
@@ -14,8 +14,8 @@ LIBRARY := As
|
||||
# All systems link the libs As, Com, Db (and again Com ??),
|
||||
# generic Unix needs also lib m:
|
||||
#
|
||||
PROD_LIBS_DEFAULT := m
|
||||
PROD_LIBS_WIN32 := -nil-
|
||||
SYS_PROD_LIBS_DEFAULT := m
|
||||
SYS_PROD_LIBS_WIN32 := -nil-
|
||||
PROD_LIBS := As Com Db Com
|
||||
|
||||
PROD := ascheck
|
||||
|
||||
@@ -127,7 +127,7 @@ LOCAL void eventCallback(struct event_handler_args eha)
|
||||
ASGINP *pasginp;
|
||||
CAPVT *pcapvt;
|
||||
ASG *pasg;
|
||||
struct dbr_sts_double *pdata = eha.dbr;
|
||||
READONLY struct dbr_sts_double *pdata = eha.dbr;
|
||||
int Ilocked=FALSE;
|
||||
|
||||
if(!caInitializing) {
|
||||
|
||||
@@ -65,6 +65,7 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000).
|
||||
#include <caeventmask.h>
|
||||
#include <dbStaticLib.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbEvent.h>
|
||||
#include <asLib.h>
|
||||
#include <asDbLib.h>
|
||||
#include <dbCommon.h>
|
||||
|
||||
@@ -72,10 +72,6 @@ int asActive = FALSE;
|
||||
/*storage for freelist */
|
||||
static void *freeListPvt = NULL;
|
||||
|
||||
/*Forward declarations for Non ANSI routines*/
|
||||
long calcPerform(double *parg,double *presult,char *post);
|
||||
long postfix(char *pinfix, char *ppostfix,short *perror);
|
||||
|
||||
#define RPCL_LEN 184
|
||||
#define DEFAULT "DEFAULT"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ static ASINPUTFUNCPTR *my_yyinput;
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(b,r,ms) (r=(*my_yyinput)(b,ms))
|
||||
|
||||
yyreset()
|
||||
static int yyreset()
|
||||
{
|
||||
line_num=1;
|
||||
BEGIN INITIAL;
|
||||
@@ -66,9 +66,13 @@ INP[A-L] {/* If A-L is changed then ASMAXINP must also be changed*/
|
||||
\n { line_num ++;}
|
||||
. {
|
||||
char message[20];
|
||||
YY_BUFFER_STATE *dummy=0;
|
||||
|
||||
sprintf(message,"invalid character '%c'",yytext[0]);
|
||||
yyerror(message);
|
||||
/*The following suppresses compiler warning messages*/
|
||||
if(FALSE) yyunput('c',message);
|
||||
if(FALSE) yy_switch_to_buffer(*dummy);
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -158,7 +160,7 @@ BDT* BdtIpOpen(char* address, int Port)
|
||||
{
|
||||
if ((pHostent = gethostbyname (address)) == NULL)
|
||||
return(NULL);
|
||||
bcopy (pHostent->h_addr, (char *) &addr, sizeof(addr));
|
||||
memcpy (&addr,pHostent->h_addr,sizeof(addr));
|
||||
printf("Converting name >%s< to IP number %08.8X\n", address, addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
TOP = ../../..
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
USR_CFLAGS = -ansi
|
||||
VX_WARN_YES = -Wall -pedantic
|
||||
|
||||
MENUS += menuConvert.h
|
||||
|
||||
BPTS += bptTypeJdegC.dbd
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
* 01 04OCT95 mrk Taken from old bldCvtTable
|
||||
*/
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <ellLib.h>
|
||||
#include <dbBase.h>
|
||||
|
||||
@@ -50,6 +50,7 @@ $ define /nolog tcp multinet_root:[multinet.include]
|
||||
$!
|
||||
$! Compile the functions and test programs
|
||||
$! Define symbol for the CC command
|
||||
$ call list_define
|
||||
$ call set_cc_command
|
||||
$ if (p1 .nes. "")
|
||||
$ then
|
||||
@@ -69,14 +70,14 @@ TEST_EVENT, -
|
||||
BSD_DEPEN, -
|
||||
IF_DEPEN, -
|
||||
VMS_DEPEN, -
|
||||
ELLLIB, -
|
||||
BUCKETLIB, -
|
||||
ENVSUBR, -
|
||||
TSSUBR, -
|
||||
[-.libcom]ELLLIB, -
|
||||
[-.libcom]BUCKETLIB, -
|
||||
[-.libcom]ENVSUBR, -
|
||||
[-.libcom]TSSUBR, -
|
||||
NEXTFIELDSUBR, -
|
||||
ASSERTUNIX, -
|
||||
ENVDATA, -
|
||||
CATIME, -
|
||||
[-.libcom]ENVDATA, -
|
||||
[-.ca]CATIME, -
|
||||
ACCTST
|
||||
$ endif
|
||||
$
|
||||
@@ -136,12 +137,19 @@ $ then
|
||||
$! turn of no prototype messages because MULTINET does not
|
||||
$! supply prototypes.
|
||||
$ cc_command:== cc /warn=(disable=IMPLICITFUNC)/float=d_float -
|
||||
/include=([], [-.include], [-.libcom]) -
|
||||
/define=("MULTINET=1")
|
||||
/define=("__STDC__=1", "MULTINET=1") -
|
||||
/include=([], [-.include], [-.include.os.vms], [-.libcom], [-.db])
|
||||
$ else
|
||||
$ cc_command:== cc /include=([], [-.include], [-.libcom]) -
|
||||
/define=("__STDC__=1", "MULTINET=1")
|
||||
$ cc_command:== cc /define=("__STDC__=1", "MULTINET=1") 'listing' -
|
||||
/include=([], [-.include], [-.include.os.vms], [-.libcom], [-.db])
|
||||
$ endif
|
||||
$
|
||||
$ endsubroutine
|
||||
$ list_define: subroutine
|
||||
$ listing == ""
|
||||
$ if p1 .eqs. "L" then listing == "/lis=list.lis /sho=incl"
|
||||
$ endsubroutine
|
||||
$
|
||||
$! ************************************************************
|
||||
|
||||
|
||||
|
||||
712
src/ca/access.c
712
src/ca/access.c
File diff suppressed because it is too large
Load Diff
185
src/ca/acctst.c
185
src/ca/acctst.c
@@ -7,6 +7,15 @@ static char *sccsId = "@(#) $Id$";
|
||||
|
||||
/*
|
||||
* $Log$
|
||||
* Revision 1.45 1997/04/29 06:07:16 jhill
|
||||
* local host connect compatible
|
||||
*
|
||||
* Revision 1.44 1997/04/10 19:26:05 jhill
|
||||
* asynch connect, faster connect, ...
|
||||
*
|
||||
* Revision 1.43 1997/01/22 21:07:27 jhill
|
||||
* fixed array test
|
||||
*
|
||||
* Revision 1.42 1996/12/12 18:51:41 jhill
|
||||
* doc
|
||||
*
|
||||
@@ -61,7 +70,7 @@ static char *sccsId = "@(#) $Id$";
|
||||
/*
|
||||
* CA
|
||||
*/
|
||||
#include <cadef.h>
|
||||
#include "cadef.h"
|
||||
|
||||
#define EVENT_ROUTINE null_event
|
||||
#define CONN_ROUTINE conn
|
||||
@@ -94,6 +103,7 @@ void write_event(struct event_handler_args args);
|
||||
void conn(struct connection_handler_args args);
|
||||
void get_cb(struct event_handler_args args);
|
||||
void accessSecurity_cb(struct access_rights_handler_args args);
|
||||
void pend_event_delay_test(dbr_double_t request);
|
||||
|
||||
void doubleTest(
|
||||
chid chan,
|
||||
@@ -173,26 +183,12 @@ int doacctst(char *pname)
|
||||
|
||||
/*
|
||||
* CA pend event delay accuracy test
|
||||
* (CA asssumes that search requests can be sent
|
||||
* at least every 25 mS on all supported os)
|
||||
*/
|
||||
{
|
||||
TS_STAMP end_time;
|
||||
TS_STAMP start_time;
|
||||
dbr_double_t delay;
|
||||
dbr_double_t request = 0.5;
|
||||
dbr_double_t accuracy;
|
||||
|
||||
tsLocalTime(&start_time);
|
||||
status = ca_pend_event(request);
|
||||
if (status != ECA_TIMEOUT) {
|
||||
SEVCHK(status, NULL);
|
||||
}
|
||||
tsLocalTime(&end_time);
|
||||
TsDiffAsDouble(&delay,&end_time,&start_time);
|
||||
accuracy = 100.0*(delay-request)/request;
|
||||
printf("CA pend event delay accuracy = %f %%\n",
|
||||
accuracy);
|
||||
assert (fabs(accuracy) < 10.0);
|
||||
}
|
||||
pend_event_delay_test(1.0);
|
||||
pend_event_delay_test(0.1);
|
||||
pend_event_delay_test(0.25);
|
||||
|
||||
size = dbr_size_n(DBR_GR_FLOAT, NUM);
|
||||
ptr = (struct dbr_gr_float *) malloc(size);
|
||||
@@ -332,7 +328,7 @@ int doacctst(char *pname)
|
||||
assert (INVALID_DB_REQ(chix4->type) == FALSE);
|
||||
|
||||
/*
|
||||
* verify connection handlers are working
|
||||
* clear chans before starting another test
|
||||
*/
|
||||
status = ca_clear_channel(chix1);
|
||||
SEVCHK(status, NULL);
|
||||
@@ -343,6 +339,53 @@ int doacctst(char *pname)
|
||||
status = ca_clear_channel(chix4);
|
||||
SEVCHK(status, NULL);
|
||||
|
||||
/*
|
||||
* verify ca_pend_io() does not see old search requests
|
||||
* (that did not specify a connection handler)
|
||||
*/
|
||||
status = ca_search_and_connect(pname, &chix1, NULL, NULL);
|
||||
SEVCHK(status, NULL);
|
||||
/*
|
||||
* channel will connect synchronously if on the
|
||||
* local host
|
||||
*/
|
||||
if (ca_state(chix1)==cs_never_conn) {
|
||||
status = ca_pend_io(1e-16);
|
||||
if (status==ECA_TIMEOUT) {
|
||||
assert(ca_state(chix1)==cs_never_conn);
|
||||
|
||||
printf("waiting on pend io verify connect...");
|
||||
fflush(stdout);
|
||||
while (ca_state(chix1)!=cs_conn) {
|
||||
ca_pend_event(0.1);
|
||||
}
|
||||
printf("done\n");
|
||||
|
||||
/*
|
||||
* we end up here if the channel isnt on the same host
|
||||
*/
|
||||
status = ca_search_and_connect(pname, &chix2, NULL, NULL);
|
||||
SEVCHK(status, NULL);
|
||||
status = ca_pend_io(1e-16);
|
||||
if (status==ECA_TIMEOUT) {
|
||||
assert(ca_state(chix2)==cs_never_conn);
|
||||
}
|
||||
else {
|
||||
assert(ca_state(chix2)==cs_conn);
|
||||
}
|
||||
status = ca_clear_channel(chix2);
|
||||
SEVCHK(status, NULL);
|
||||
}
|
||||
else {
|
||||
assert(ca_state(chix1)==cs_conn);
|
||||
}
|
||||
}
|
||||
status = ca_clear_channel(chix1);
|
||||
SEVCHK(status, NULL);
|
||||
|
||||
/*
|
||||
* verify connection handlers are working
|
||||
*/
|
||||
status = ca_search_and_connect(pname, &chix1, conn, NULL);
|
||||
SEVCHK(status, NULL);
|
||||
status = ca_search_and_connect(pname, &chix2, conn, NULL);
|
||||
@@ -352,12 +395,12 @@ int doacctst(char *pname)
|
||||
status = ca_search_and_connect(pname, &chix4, conn, NULL);
|
||||
SEVCHK(status, NULL);
|
||||
|
||||
ca_pend_event(1.0);
|
||||
while (conn_cb_count != 4){
|
||||
ca_pend_event(1.0);
|
||||
printf("waiting on connect...");
|
||||
fflush(stdout);
|
||||
printf("waiting on conn handler call back connect...");
|
||||
fflush(stdout);
|
||||
while (conn_cb_count != 4) {
|
||||
ca_pend_event(0.1);
|
||||
}
|
||||
printf("done\n");
|
||||
|
||||
printf("Read Access=%d Write Access=%d\n",
|
||||
ca_read_access(chix1),
|
||||
@@ -406,6 +449,23 @@ int doacctst(char *pname)
|
||||
printf ("done\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that we can do IO with the new types for ALH
|
||||
*/
|
||||
#if 0
|
||||
if(ca_read_access(chix4)&&ca_write_access(chix4)){
|
||||
{
|
||||
dbr_put_ackt_t acktIn=1u;
|
||||
dbr_put_acks_t acksIn=1u;
|
||||
struct dbr_stsack_string stsackOut;
|
||||
|
||||
SEVCHK (ca_put(DBR_PUT_ACKT, chix4, &acktIn),NULL);
|
||||
SEVCHK (ca_put(DBR_PUT_ACKS, chix4, &acksIn),NULL);
|
||||
SEVCHK (ca_get(DBR_STSACK_STRING, chix4, &stsackOut),NULL);
|
||||
SEVCHK (ca_pend_io(2000.0),NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Verify that we can write and then read back
|
||||
* the same analog value (DBR_FLOAT)
|
||||
@@ -426,22 +486,34 @@ int doacctst(char *pname)
|
||||
base = FLT_MIN;
|
||||
for (i=FLT_MIN_EXP; i<FLT_MAX_EXP; i+=FLT_MAX_EXP/10) {
|
||||
incr = (dbr_float_t) ldexp (0.5F,i);
|
||||
iter = (unsigned long) (FLT_MAX/fabs(incr));
|
||||
iter = min (iter,10);
|
||||
if (fabs(incr)>FLT_MAX/10.0) {
|
||||
iter = (unsigned long) (FLT_MAX/fabs(incr));
|
||||
}
|
||||
else {
|
||||
iter = 10.0;
|
||||
}
|
||||
floatTest(chix1, base, incr, epsil, iter);
|
||||
}
|
||||
base = FLT_MAX;
|
||||
for (i=FLT_MIN_EXP; i<FLT_MAX_EXP; i+=FLT_MAX_EXP/10) {
|
||||
incr = (dbr_float_t) - ldexp (0.5F,i);
|
||||
iter = (unsigned long) (FLT_MAX/fabs(incr));
|
||||
iter = min (iter,10);
|
||||
if (fabs(incr)>FLT_MAX/10.0) {
|
||||
iter = (unsigned long) (FLT_MAX/fabs(incr));
|
||||
}
|
||||
else {
|
||||
iter = 10.0;
|
||||
}
|
||||
floatTest(chix1, base, incr, epsil, iter);
|
||||
}
|
||||
base = - FLT_MAX;
|
||||
for (i=FLT_MIN_EXP; i<FLT_MAX_EXP; i+=FLT_MAX_EXP/10) {
|
||||
incr = (dbr_float_t) ldexp (0.5F,i);
|
||||
iter = (unsigned long) (FLT_MAX/fabs(incr));
|
||||
iter = min (iter,10);
|
||||
if (fabs(incr)>FLT_MAX/10.0) {
|
||||
iter = (unsigned long) (FLT_MAX/fabs(incr));
|
||||
}
|
||||
else {
|
||||
iter = 10.0;
|
||||
}
|
||||
floatTest(chix1, base, incr, epsil, iter);
|
||||
}
|
||||
printf ("done\n");
|
||||
@@ -466,22 +538,34 @@ int doacctst(char *pname)
|
||||
base = DBL_MIN;
|
||||
for (i=DBL_MIN_EXP; i<DBL_MAX_EXP; i+=DBL_MAX_EXP/10) {
|
||||
incr = ldexp (0.5,i);
|
||||
iter = (unsigned long) (DBL_MAX/fabs(incr));
|
||||
iter = min (iter,10);
|
||||
if (fabs(incr)>DBL_MAX/10.0) {
|
||||
iter = (unsigned long) (DBL_MAX/fabs(incr));
|
||||
}
|
||||
else {
|
||||
iter = 10.0;
|
||||
}
|
||||
doubleTest(chix1, base, incr, epsil, iter);
|
||||
}
|
||||
base = DBL_MAX;
|
||||
for (i=DBL_MIN_EXP; i<DBL_MAX_EXP; i+=DBL_MAX_EXP/10) {
|
||||
incr = - ldexp (0.5,i);
|
||||
iter = (unsigned long) (DBL_MAX/fabs(incr));
|
||||
iter = min (iter,10);
|
||||
if (fabs(incr)>DBL_MAX/10.0) {
|
||||
iter = (unsigned long) (DBL_MAX/fabs(incr));
|
||||
}
|
||||
else {
|
||||
iter = 10.0;
|
||||
}
|
||||
doubleTest(chix1, base, incr, epsil, iter);
|
||||
}
|
||||
base = - DBL_MAX;
|
||||
for (i=DBL_MIN_EXP; i<DBL_MAX_EXP; i+=DBL_MAX_EXP/10) {
|
||||
incr = ldexp (0.5,i);
|
||||
iter = (unsigned long) (DBL_MAX/fabs(incr));
|
||||
iter = min (iter,10);
|
||||
if (fabs(incr)>DBL_MAX/10.0) {
|
||||
iter = (unsigned long) (DBL_MAX/fabs(incr));
|
||||
}
|
||||
else {
|
||||
iter = 10.0;
|
||||
}
|
||||
doubleTest(chix1, base, incr, epsil, iter);
|
||||
}
|
||||
printf ("done\n");
|
||||
@@ -848,7 +932,6 @@ int doacctst(char *pname)
|
||||
accuracy = 100.0*(delay-request)/request;
|
||||
printf("CA pend event delay accuracy = %f %%\n",
|
||||
accuracy);
|
||||
assert (fabs(accuracy) < 10.0);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -881,6 +964,30 @@ int doacctst(char *pname)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* pend_event_delay_test()
|
||||
*/
|
||||
void pend_event_delay_test(dbr_double_t request)
|
||||
{
|
||||
int status;
|
||||
TS_STAMP end_time;
|
||||
TS_STAMP start_time;
|
||||
dbr_double_t delay;
|
||||
dbr_double_t accuracy;
|
||||
|
||||
tsLocalTime(&start_time);
|
||||
status = ca_pend_event(request);
|
||||
if (status != ECA_TIMEOUT) {
|
||||
SEVCHK(status, NULL);
|
||||
}
|
||||
tsLocalTime(&end_time);
|
||||
TsDiffAsDouble(&delay,&end_time,&start_time);
|
||||
accuracy = 100.0*(delay-request)/request;
|
||||
printf("CA pend event delay = %f sec results in accuracy = %f %%\n",
|
||||
request, accuracy);
|
||||
assert (fabs(accuracy) < 10.0);
|
||||
}
|
||||
|
||||
void floatTest(
|
||||
chid chan,
|
||||
dbr_float_t beginValue,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <envDefs.h>
|
||||
#include "envDefs.h"
|
||||
|
||||
void caSetupAddrList(
|
||||
ELLLIST *pList,
|
||||
@@ -19,12 +19,13 @@ void caDiscoverInterfaces(
|
||||
|
||||
void caAddConfiguredAddr(
|
||||
ELLLIST *pList,
|
||||
ENV_PARAM *pEnv,
|
||||
const ENV_PARAM *pEnv,
|
||||
SOCKET socket,
|
||||
int port);
|
||||
|
||||
int local_addr(SOCKET socket, struct sockaddr_in *plcladdr);
|
||||
unsigned short caFetchPortConfig(ENV_PARAM *pEnv, unsigned short defaultPort);
|
||||
unsigned short caFetchPortConfig(const ENV_PARAM *pEnv,
|
||||
unsigned short defaultPort);
|
||||
|
||||
typedef union ca_addr {
|
||||
struct sockaddr_in in;
|
||||
|
||||
@@ -52,6 +52,7 @@ int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
unsigned long freespace;
|
||||
SOCKET maxfd;
|
||||
caFDInfo *pfdi;
|
||||
int ioPending;
|
||||
|
||||
LOCK;
|
||||
pfdi = (caFDInfo *) ellGet(&ca_static->fdInfoFreeList);
|
||||
@@ -70,11 +71,12 @@ int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
FD_ZERO (&pfdi->writeMask);
|
||||
|
||||
maxfd = 0;
|
||||
ioPending = FALSE;
|
||||
for( piiu = (IIU *) iiuList.node.next;
|
||||
piiu;
|
||||
piiu = (IIU *) piiu->node.next) {
|
||||
|
||||
if (!piiu->conn_up) {
|
||||
if (piiu->state==iiu_disconnected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -106,40 +108,70 @@ int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
|
||||
/*
|
||||
* Dont bother receiving if we have insufficient
|
||||
* space for the maximum UDP message
|
||||
* space for the maximum UDP message, or space
|
||||
* for one TCP byte.
|
||||
*/
|
||||
if (flags&CA_DO_RECVS) {
|
||||
freespace = cacRingBufferWriteSize (&piiu->recv, TRUE);
|
||||
if (freespace>=piiu->minfreespace) {
|
||||
maxfd = max (maxfd,piiu->sock_chan);
|
||||
FD_SET (piiu->sock_chan, &pfdi->readMask);
|
||||
piiu->recvPending = TRUE;
|
||||
ioPending = TRUE;
|
||||
}
|
||||
else {
|
||||
piiu->recvPending = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
piiu->recvPending = FALSE;
|
||||
}
|
||||
|
||||
if (flags&CA_DO_SENDS) {
|
||||
if (piiu->state==iiu_connecting) {
|
||||
FD_SET (piiu->sock_chan, &pfdi->writeMask);
|
||||
ioPending = TRUE;
|
||||
}
|
||||
else if (flags&CA_DO_SENDS || piiu->pushPending) {
|
||||
if (cacRingBufferReadSize(&piiu->send, FALSE)>0) {
|
||||
maxfd = max (maxfd,piiu->sock_chan);
|
||||
FD_SET (piiu->sock_chan, &pfdi->writeMask);
|
||||
ioPending = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
# if defined(__hpux)
|
||||
/*
|
||||
* win32 requires this (others will
|
||||
* run faster with this installed)
|
||||
*/
|
||||
if ( !ioPending &&
|
||||
ptimeout->tv_sec==0 &&
|
||||
ptimeout->tv_usec==0 ) {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
# if defined(__hpux)
|
||||
# define HPCAST (int *)
|
||||
# else
|
||||
# define HPCAST
|
||||
# endif
|
||||
status = select(
|
||||
maxfd+1,
|
||||
(int *)&pfdi->readMask,
|
||||
(int *)&pfdi->writeMask,
|
||||
(int *)NULL,
|
||||
HPCAST &pfdi->readMask,
|
||||
HPCAST &pfdi->writeMask,
|
||||
HPCAST NULL,
|
||||
&autoTimeOut);
|
||||
# else
|
||||
status = select(
|
||||
maxfd+1,
|
||||
&pfdi->readMask,
|
||||
&pfdi->writeMask,
|
||||
NULL,
|
||||
&autoTimeOut);
|
||||
# endif
|
||||
if (status<0) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
|
||||
if (errnoCpy!=EINTR) {
|
||||
ca_printf (
|
||||
"CAC: unexpected select fail: %s\n",
|
||||
strerror(SOCKERRNO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get a new time stamp if we have been waiting
|
||||
@@ -149,34 +181,46 @@ int cac_select_io(struct timeval *ptimeout, int flags)
|
||||
cac_gettimeval (&ca_static->currentTime);
|
||||
}
|
||||
|
||||
if (status<0) {
|
||||
if (SOCKERRNO == EINTR) {
|
||||
}
|
||||
else if (SOCKERRNO == EWOULDBLOCK) {
|
||||
ca_printf("CAC: blocked at select ?\n");
|
||||
}
|
||||
else if (SOCKERRNO == ESRCH) {
|
||||
}
|
||||
else {
|
||||
ca_printf (
|
||||
"CAC: unexpected select fail: %s\n",
|
||||
strerror(SOCKERRNO));
|
||||
}
|
||||
}
|
||||
|
||||
LOCK;
|
||||
if (status>0) {
|
||||
/*
|
||||
* must run through the IIU list even if no IO is pending
|
||||
* if any of the IOCs are in flow control (so that an exit
|
||||
* flow control msg can be sent to each of them that are)
|
||||
*/
|
||||
if (status>0 ||
|
||||
(ca_static->ca_number_iiu_in_fc>0u&&status>=0) ) {
|
||||
for ( piiu = (IIU *) iiuList.node.next;
|
||||
piiu;
|
||||
piiu = (IIU *) piiu->node.next) {
|
||||
|
||||
if (!piiu->conn_up) {
|
||||
if (piiu->state==iiu_disconnected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(piiu->sock_chan,&pfdi->readMask)) {
|
||||
(*piiu->recvBytes)(piiu);
|
||||
/*
|
||||
* if we were not blocking and there is a
|
||||
* message present then start to suspect that
|
||||
* we are getting behind
|
||||
*/
|
||||
if (piiu->sock_proto==IPPROTO_TCP) {
|
||||
if (ptimeout->tv_sec==0
|
||||
|| ptimeout->tv_usec==0) {
|
||||
flow_control_on(piiu);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (piiu->recvPending) {
|
||||
/*
|
||||
* if we are looking for incoming messages
|
||||
* and there are none then we are certain that
|
||||
* we are not getting behind
|
||||
*/
|
||||
if (piiu->sock_proto==IPPROTO_TCP) {
|
||||
flow_control_off(piiu);
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(piiu->sock_chan,&pfdi->writeMask)) {
|
||||
(*piiu->sendBytes)(piiu);
|
||||
|
||||
@@ -45,15 +45,15 @@ caFetchPortConfig
|
||||
caAddConfiguredAddr
|
||||
caDiscoverInterfaces
|
||||
ca_printf
|
||||
ca_message_text
|
||||
ca_message_text
|
||||
ca_message
|
||||
cac_gettimeval
|
||||
dbr_value_size
|
||||
dbr_value_offset
|
||||
dbf_text
|
||||
dbf_text_invalid
|
||||
dbf_text_dim
|
||||
dbr_text
|
||||
dbr_text_invalid
|
||||
dbr_text_dim
|
||||
dbr_size
|
||||
dbr_value_size
|
||||
dbr_value_offset
|
||||
dbf_text
|
||||
dbf_text_invalid
|
||||
dbf_text_dim
|
||||
dbr_text
|
||||
dbr_text_invalid
|
||||
dbr_text_dim
|
||||
dbr_size
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.3 1997/01/22 21:08:17 jhill
|
||||
* removed use of ## for VAXC port
|
||||
*
|
||||
* Revision 1.2 1996/09/16 16:32:49 jhill
|
||||
* added CA version string
|
||||
*
|
||||
@@ -68,6 +71,9 @@
|
||||
*
|
||||
* .10 050594 joh New command added for CA V4.3 - wakeup the server
|
||||
* $Log$
|
||||
* Revision 1.3 1997/01/22 21:08:17 jhill
|
||||
* removed use of ## for VAXC port
|
||||
*
|
||||
* Revision 1.2 1996/09/16 16:32:49 jhill
|
||||
* added CA version string
|
||||
*
|
||||
@@ -87,8 +93,8 @@
|
||||
* TCP/UDP port number (bumped each major protocol change)
|
||||
*/
|
||||
#define CA_PROTOCOL_VERSION 4u
|
||||
#define CA_MINOR_VERSION 7u
|
||||
#define CA_VERSION_STRING "4.7"
|
||||
#define CA_MINOR_VERSION 8u
|
||||
#define CA_VERSION_STRING "4.8"
|
||||
#define CA_UKN_MINOR_VERSION 0u /* unknown minor version */
|
||||
#if CA_PROTOCOL_VERSION == 4u
|
||||
#define CA_V41(MAJOR,MINOR) ((MINOR)>=1u)
|
||||
@@ -98,6 +104,7 @@
|
||||
#define CA_V45(MAJOR,MINOR) ((MINOR)>=5u)
|
||||
#define CA_V46(MAJOR,MINOR) ((MINOR)>=6u)
|
||||
#define CA_V47(MAJOR,MINOR) ((MINOR)>=7u)
|
||||
#define CA_V48(MAJOR,MINOR) ((MINOR)>=8u)
|
||||
#elif CA_PROTOCOL_VERSION > 4u
|
||||
#define CA_V41(MAJOR,MINOR) ( 1u )
|
||||
#define CA_V42(MAJOR,MINOR) ( 1u )
|
||||
@@ -106,6 +113,7 @@
|
||||
#define CA_V45(MAJOR,MINOR) ( 1u )
|
||||
#define CA_V46(MAJOR,MINOR) ( 1u )
|
||||
#define CA_V47(MAJOR,MINOR) ( 1u )
|
||||
#define CA_V48(MAJOR,MINOR) ( 1u )
|
||||
#else
|
||||
#define CA_V41(MAJOR,MINOR) ( 0u )
|
||||
#define CA_V42(MAJOR,MINOR) ( 0u )
|
||||
@@ -114,6 +122,7 @@
|
||||
#define CA_V45(MAJOR,MINOR) ( 0u )
|
||||
#define CA_V46(MAJOR,MINOR) ( 0u )
|
||||
#define CA_V47(MAJOR,MINOR) ( 0u )
|
||||
#define CA_V48(MAJOR,MINOR) ( 0u )
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iocinf.h>
|
||||
#include "iocinf.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
207
src/ca/cadef.h
207
src/ca/cadef.h
@@ -86,7 +86,7 @@ extern "C" {
|
||||
#define CAC_ANSI_FUNC_PROTO
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
#include "shareLib.h"
|
||||
|
||||
|
||||
#ifndef HDRVERSIONID
|
||||
@@ -109,19 +109,19 @@ HDRVERSIONID(cadefh, "@(#) $Id$")
|
||||
#endif
|
||||
|
||||
#ifndef INCLdb_accessh
|
||||
#include <db_access.h>
|
||||
#include "db_access.h"
|
||||
#endif /* INCLdb_accessh */
|
||||
|
||||
#ifndef INCLcaerrh
|
||||
#include <caerr.h>
|
||||
#include "caerr.h"
|
||||
#endif /* INCLcaerrh */
|
||||
|
||||
#ifndef INCLcaeventmaskh
|
||||
#include <caeventmask.h>
|
||||
#include "caeventmask.h"
|
||||
#endif /* INCLcaeventmaskh */
|
||||
|
||||
#ifndef INCLellLibh
|
||||
#include <ellLib.h>
|
||||
#include "ellLib.h"
|
||||
#endif /* INCLellLibh */
|
||||
|
||||
/*
|
||||
@@ -143,8 +143,7 @@ HDRVERSIONID(cadefh, "@(#) $Id$")
|
||||
* here is the preferred way to load the puser ptr associated with
|
||||
* channel (the cast removes const)
|
||||
*/
|
||||
#define ca_set_puser(CHID,PUSER) \
|
||||
(((struct channel_in_use *)CHID)->puser=(PUSER))
|
||||
#define ca_set_puser(CHID,PUSER) ((CHID)->puser=(const void *)(PUSER))
|
||||
#define ca_host_name(CHID) ca_host_name_function(CHID)
|
||||
#define ca_read_access(CHID) ((CHID)->ar.read_access)
|
||||
#define ca_write_access(CHID) ((CHID)->ar.write_access)
|
||||
@@ -169,8 +168,7 @@ typedef struct ca_access_rights{
|
||||
/* Format for the arguments to user connection handlers */
|
||||
struct channel_in_use;
|
||||
struct connection_handler_args{
|
||||
READONLY struct channel_in_use
|
||||
*chid; /* Channel id */
|
||||
struct channel_in_use *chid; /* Channel id */
|
||||
long op; /* External codes for CA op */
|
||||
};
|
||||
|
||||
@@ -182,8 +180,7 @@ typedef void caCh();
|
||||
|
||||
/* Format for the arguments to user access rights handlers */
|
||||
struct access_rights_handler_args{
|
||||
READONLY struct channel_in_use
|
||||
*chid; /* Channel id */
|
||||
struct channel_in_use *chid; /* Channel id */
|
||||
caar ar; /* New access rights state */
|
||||
};
|
||||
|
||||
@@ -193,22 +190,25 @@ typedef void caArh(struct access_rights_handler_args args);
|
||||
typedef void caArh();
|
||||
#endif /*CAC_ANSI_FUNC_PROTO*/
|
||||
|
||||
/*
|
||||
* The fields in this structure may change or even vanish in the future.
|
||||
* Please use the macros above to access the information in this structure.
|
||||
*/
|
||||
struct channel_in_use{
|
||||
ELLNODE node; /* list ptrs */
|
||||
short type; /* database field type */
|
||||
#define TYPENOTCONN (-1) /* the type when disconnected */
|
||||
unsigned short count; /* array element count */
|
||||
ELLNODE node; /* list ptrs */
|
||||
short type; /* database field type */
|
||||
#define TYPENOTCONN (-1) /* the type when disconnected */
|
||||
unsigned short count; /* array element count */
|
||||
union{
|
||||
unsigned sid; /* server id */
|
||||
struct dbAddr *paddr; /* database address */
|
||||
unsigned sid; /* server id */
|
||||
struct dbAddr *paddr; /* database address */
|
||||
} id;
|
||||
READONLY void *puser; /* user available area */
|
||||
enum channel_state state; /* connected/ disconnected etc */
|
||||
caar ar; /* access rights */
|
||||
const void *puser; /* user available area */
|
||||
short state; /* connected/ disconnected etc */
|
||||
unsigned short retrySeqNo; /* search retry seq number */
|
||||
caar ar; /* access rights */
|
||||
|
||||
|
||||
/*
|
||||
* The following fields may change or even vanish in the future
|
||||
*/
|
||||
caCh *pConnFunc;
|
||||
caArh *pAccessRightsFunc;
|
||||
ELLLIST eventq;
|
||||
@@ -218,15 +218,16 @@ struct channel_in_use{
|
||||
#ifdef vxWorks
|
||||
void *ppn; /* ptr to optional put notify blk */
|
||||
#endif /* vxWorks */
|
||||
unsigned claimPending:1; /* claim msg was sent if T */
|
||||
/*
|
||||
* channel name stored directly after this structure in a
|
||||
* null terminated string.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef READONLY struct channel_in_use *chid;
|
||||
typedef struct channel_in_use *chid;
|
||||
typedef long chtype;
|
||||
typedef READONLY struct pending_event *evid;
|
||||
typedef struct pending_event *evid;
|
||||
typedef double ca_real;
|
||||
|
||||
/* The conversion routine to call for each type */
|
||||
@@ -236,7 +237,7 @@ typedef double ca_real;
|
||||
/* argument passed to event handlers and callback handlers */
|
||||
struct event_handler_args{
|
||||
void *usr; /* User argument supplied when event added */
|
||||
READONLY struct channel_in_use
|
||||
struct channel_in_use
|
||||
*chid; /* Channel id */
|
||||
long type; /* the type of the value returned */
|
||||
long count; /* the element count of the item returned */
|
||||
@@ -251,7 +252,7 @@ struct pending_event{
|
||||
#else /*CAC_ANSI_FUNC_PROTO*/
|
||||
void (*usr_func)();
|
||||
#endif /*CAC_ANSI_FUNC_PROTO*/
|
||||
READONLY void *usr_arg;
|
||||
const void *usr_arg;
|
||||
chid chan;
|
||||
chtype type; /* requested type for local CA */
|
||||
unsigned long count; /* requested count for local CA */
|
||||
@@ -266,7 +267,7 @@ struct pending_event{
|
||||
unsigned short mask;
|
||||
};
|
||||
|
||||
void epicsShareAPI ca_test_event
|
||||
epicsShareFunc void epicsShareAPI ca_test_event
|
||||
(
|
||||
#ifdef CAC_ANSI_FUNC_PROTO
|
||||
struct event_handler_args
|
||||
@@ -276,15 +277,15 @@ void epicsShareAPI ca_test_event
|
||||
/* Format for the arguments to user exception handlers */
|
||||
struct exception_handler_args{
|
||||
void *usr; /* User argument supplied when event added */
|
||||
READONLY struct channel_in_use
|
||||
struct channel_in_use
|
||||
*chid; /* Channel id */
|
||||
long type; /* Requested type for the operation */
|
||||
long count; /* Requested count for the operation */
|
||||
void *addr; /* User's address to write results of CA_OP_GET */
|
||||
long stat; /* Channel access std status code */
|
||||
long op; /* External codes for channel access operations */
|
||||
const char *ctx; /* A character string containing context info */
|
||||
const char *pFile; /* source file name (may be NULL) */
|
||||
READONLY char *ctx; /* A character string containing context info */
|
||||
READONLY char *pFile; /* source file name (may be NULL) */
|
||||
unsigned lineNo; /* source file line number */
|
||||
};
|
||||
|
||||
@@ -312,14 +313,14 @@ struct exception_handler_args{
|
||||
/* */
|
||||
/* Must be called once before calling any of the other routines */
|
||||
/************************************************************************/
|
||||
int epicsShareAPI ca_task_initialize (void);
|
||||
epicsShareFunc int epicsShareAPI ca_task_initialize (void);
|
||||
|
||||
/************************************************************************/
|
||||
/* Remove CA facility from your task */
|
||||
/* */
|
||||
/* Normally called automatically at task exit */
|
||||
/************************************************************************/
|
||||
int epicsShareAPI ca_task_exit (void);
|
||||
epicsShareFunc int epicsShareAPI ca_task_exit (void);
|
||||
|
||||
/************************************************************************
|
||||
* anachronistic entry points *
|
||||
@@ -361,7 +362,7 @@ ca_search_and_connect(pChanName, pChanID, 0, 0)
|
||||
* (fetched later by ca_puser(CHID))
|
||||
* (passed as void * arg to (*pFunc)() above)
|
||||
*/
|
||||
int epicsShareAPI ca_search_and_connect
|
||||
epicsShareFunc int epicsShareAPI ca_search_and_connect
|
||||
(
|
||||
const char *pChanName,
|
||||
chid *pChanID,
|
||||
@@ -380,7 +381,7 @@ int epicsShareAPI ca_search_and_connect
|
||||
* (fetched later by ca_puser(CHID))
|
||||
* (passed as void * arg to (*pFunc)() above)
|
||||
*/
|
||||
int epicsShareAPI ca_build_and_connect
|
||||
epicsShareFunc int epicsShareAPI ca_build_and_connect
|
||||
(
|
||||
const char *pChanName,
|
||||
chtype, /* pass TYPENOTCONN */
|
||||
@@ -397,7 +398,7 @@ int epicsShareAPI ca_build_and_connect
|
||||
* chan R channel identifier
|
||||
* pfunc R address of connection call-back function
|
||||
*/
|
||||
int epicsShareAPI ca_change_connection_event
|
||||
epicsShareFunc int epicsShareAPI ca_change_connection_event
|
||||
(
|
||||
chid chan,
|
||||
void (*pfunc)(struct connection_handler_args)
|
||||
@@ -409,7 +410,7 @@ int epicsShareAPI ca_change_connection_event
|
||||
* chan R channel identifier
|
||||
* pfunc R address of access rights call-back function
|
||||
*/
|
||||
int epicsShareAPI ca_replace_access_rights_event(
|
||||
epicsShareFunc int epicsShareAPI ca_replace_access_rights_event(
|
||||
chid chan,
|
||||
void (*pfunc)(struct access_rights_handler_args)
|
||||
);
|
||||
@@ -423,7 +424,7 @@ int epicsShareAPI ca_replace_access_rights_event(
|
||||
* pArg R copy of this pointer passed to exception
|
||||
* call-back function
|
||||
*/
|
||||
int epicsShareAPI ca_add_exception_event
|
||||
epicsShareFunc int epicsShareAPI ca_add_exception_event
|
||||
(
|
||||
void (*pfunc) (struct exception_handler_args),
|
||||
const void *pArg
|
||||
@@ -435,7 +436,7 @@ int epicsShareAPI ca_add_exception_event
|
||||
*
|
||||
* chanId R channel ID
|
||||
*/
|
||||
int epicsShareAPI ca_clear_channel
|
||||
epicsShareFunc int epicsShareAPI ca_clear_channel
|
||||
(
|
||||
chid chanId
|
||||
);
|
||||
@@ -483,7 +484,7 @@ ca_array_put(DBR_FLOAT, 1u, chan, (const dbr_float_t *) pValue)
|
||||
* chan R channel identifier
|
||||
* pValue R new channel value copied from this location
|
||||
*/
|
||||
int epicsShareAPI ca_array_put
|
||||
epicsShareFunc int epicsShareAPI ca_array_put
|
||||
(
|
||||
chtype type,
|
||||
unsigned long count,
|
||||
@@ -508,7 +509,7 @@ int epicsShareAPI ca_array_put
|
||||
* pFunc R pointer to call-back function
|
||||
* pArg R copy of this pointer passed to pFunc
|
||||
*/
|
||||
int epicsShareAPI ca_array_put_callback
|
||||
epicsShareFunc int epicsShareAPI ca_array_put_callback
|
||||
(
|
||||
chtype type,
|
||||
unsigned long count,
|
||||
@@ -562,7 +563,7 @@ ca_array_get(DBR_FLOAT, 1u, chan, (dbr_float_t *)(pValue))
|
||||
* chan R channel identifier
|
||||
* pValue W channel value copied to this location
|
||||
*/
|
||||
int epicsShareAPI ca_array_get
|
||||
epicsShareFunc int epicsShareAPI ca_array_get
|
||||
(
|
||||
chtype type,
|
||||
unsigned long count,
|
||||
@@ -621,7 +622,7 @@ ca_array_get_callback(type, 1u, chan, pFunc, pArg)
|
||||
* pFunc R pointer to call-back function
|
||||
* pArg R copy of this pointer passed to pFunc
|
||||
*/
|
||||
int epicsShareAPI ca_array_get_callback
|
||||
epicsShareFunc int epicsShareAPI ca_array_get_callback
|
||||
(
|
||||
chtype type,
|
||||
unsigned long count,
|
||||
@@ -681,7 +682,7 @@ ca_add_masked_array_event(TYPE,COUNT,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID, DBE
|
||||
* pEventID W event id written at specified address
|
||||
* mask R event mask - one of {DBE_VALUE, DBE_ALARM, DBE_LOG}
|
||||
*/
|
||||
int epicsShareAPI ca_add_masked_array_event
|
||||
epicsShareFunc int epicsShareAPI ca_add_masked_array_event
|
||||
(
|
||||
chtype type,
|
||||
unsigned long count,
|
||||
@@ -705,7 +706,7 @@ int epicsShareAPI ca_add_masked_array_event
|
||||
*
|
||||
* eventID R event id
|
||||
*/
|
||||
int epicsShareAPI ca_clear_event
|
||||
epicsShareFunc int epicsShareAPI ca_clear_event
|
||||
(
|
||||
evid eventID
|
||||
);
|
||||
@@ -771,7 +772,7 @@ int epicsShareAPI ca_clear_event
|
||||
* have completed)
|
||||
* F: wait for the entire delay to expire
|
||||
*/
|
||||
int epicsShareAPI ca_pend
|
||||
epicsShareFunc int epicsShareAPI ca_pend
|
||||
(
|
||||
ca_real timeOut,
|
||||
int early
|
||||
@@ -783,7 +784,7 @@ int epicsShareAPI ca_pend
|
||||
* returns TRUE when get requests (or search requests with null
|
||||
* connection handler pointer) are outstanding
|
||||
*/
|
||||
int epicsShareAPI ca_test_io (void);
|
||||
epicsShareFunc int epicsShareAPI ca_test_io (void);
|
||||
|
||||
/************************************************************************/
|
||||
/* Send out all outstanding messages in the send queue */
|
||||
@@ -791,7 +792,7 @@ int epicsShareAPI ca_test_io (void);
|
||||
/*
|
||||
* ca_flush_io()
|
||||
*/
|
||||
int epicsShareAPI ca_flush_io (void);
|
||||
epicsShareFunc int epicsShareAPI ca_flush_io (void);
|
||||
|
||||
|
||||
/*
|
||||
@@ -800,7 +801,7 @@ int epicsShareAPI ca_flush_io (void);
|
||||
* errorCode R status returned from channel access function
|
||||
* pCtxStr R context string included with error print out
|
||||
*/
|
||||
void epicsShareAPI ca_signal
|
||||
epicsShareFunc void epicsShareAPI ca_signal
|
||||
(
|
||||
long errorCode,
|
||||
const char *pCtxStr
|
||||
@@ -814,7 +815,7 @@ void epicsShareAPI ca_signal
|
||||
* lineNo R line number included with error print out
|
||||
*
|
||||
*/
|
||||
void epicsShareAPI ca_signal_with_file_and_lineno
|
||||
epicsShareFunc void epicsShareAPI ca_signal_with_file_and_lineno
|
||||
(
|
||||
long errorCode,
|
||||
const char *pCtxStr,
|
||||
@@ -841,7 +842,7 @@ void epicsShareAPI ca_signal_with_file_and_lineno
|
||||
*
|
||||
* channel R channel identifier
|
||||
*/
|
||||
const char * epicsShareAPI ca_host_name_function ( chid channel);
|
||||
epicsShareFunc const char * epicsShareAPI ca_host_name_function ( chid channel);
|
||||
|
||||
/*
|
||||
* CA_ADD_FD_REGISTRATION
|
||||
@@ -863,7 +864,7 @@ typedef void CAFDHANDLER(void *parg, int fd, int opened);
|
||||
* when an fd is created or deleted
|
||||
* pArg R argument passed to above function
|
||||
*/
|
||||
int epicsShareAPI ca_add_fd_registration
|
||||
epicsShareFunc int epicsShareAPI ca_add_fd_registration
|
||||
(
|
||||
CAFDHANDLER *pHandler,
|
||||
const void *pArg
|
||||
@@ -875,7 +876,7 @@ int epicsShareAPI ca_add_fd_registration
|
||||
* tid R task id
|
||||
*/
|
||||
#ifdef vxWorks
|
||||
int epicsShareAPI ca_channel_status( int tid);
|
||||
epicsShareFunc int epicsShareAPI ca_channel_status( int tid);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -914,7 +915,7 @@ typedef unsigned CA_SYNC_GID;
|
||||
*
|
||||
* pgid W pointer to sync group id that will be written
|
||||
*/
|
||||
int epicsShareAPI ca_sg_create( CA_SYNC_GID * pgid);
|
||||
epicsShareFunc int epicsShareAPI ca_sg_create( CA_SYNC_GID * pgid);
|
||||
|
||||
/*
|
||||
* ca_sg_delete()
|
||||
@@ -923,7 +924,7 @@ int epicsShareAPI ca_sg_create( CA_SYNC_GID * pgid);
|
||||
*
|
||||
* gid R sync group id
|
||||
*/
|
||||
int epicsShareAPI ca_sg_delete(const CA_SYNC_GID gid);
|
||||
epicsShareFunc int epicsShareAPI ca_sg_delete(const CA_SYNC_GID gid);
|
||||
|
||||
/*
|
||||
* ca_sg_block()
|
||||
@@ -934,7 +935,7 @@ int epicsShareAPI ca_sg_delete(const CA_SYNC_GID gid);
|
||||
* timeout R wait for this duration prior to timing out
|
||||
* and returning ECA_TIMEOUT
|
||||
*/
|
||||
int epicsShareAPI ca_sg_block(const CA_SYNC_GID gid, ca_real timeout);
|
||||
epicsShareFunc int epicsShareAPI ca_sg_block(const CA_SYNC_GID gid, ca_real timeout);
|
||||
|
||||
/*
|
||||
* ca_sg_test()
|
||||
@@ -945,14 +946,14 @@ int epicsShareAPI ca_sg_block(const CA_SYNC_GID gid, ca_real timeout);
|
||||
*
|
||||
* returns one of ECA_BADSYNCGRP, ECA_IOINPROGRESS, ECA_IODONE
|
||||
*/
|
||||
int epicsShareAPI ca_sg_test(const CA_SYNC_GID gid);
|
||||
epicsShareFunc int epicsShareAPI ca_sg_test(const CA_SYNC_GID gid);
|
||||
|
||||
/*
|
||||
* ca_sg_reset
|
||||
*
|
||||
* gid R sync group id
|
||||
*/
|
||||
int epicsShareAPI ca_sg_reset(const CA_SYNC_GID gid);
|
||||
epicsShareFunc int epicsShareAPI ca_sg_reset(const CA_SYNC_GID gid);
|
||||
|
||||
/*
|
||||
* ca_sg_array_get()
|
||||
@@ -966,7 +967,7 @@ int epicsShareAPI ca_sg_reset(const CA_SYNC_GID gid);
|
||||
* chan R channel identifier
|
||||
* pValue W channel value copied to this location
|
||||
*/
|
||||
int epicsShareAPI ca_sg_array_get
|
||||
epicsShareFunc int epicsShareAPI ca_sg_array_get
|
||||
(
|
||||
const CA_SYNC_GID gid,
|
||||
chtype type, /* TYPE R channel type */
|
||||
@@ -987,7 +988,7 @@ int epicsShareAPI ca_sg_array_get
|
||||
* chan R channel identifier
|
||||
* pValue R new channel value copied from this location
|
||||
*/
|
||||
int epicsShareAPI ca_sg_array_put
|
||||
epicsShareFunc int epicsShareAPI ca_sg_array_put
|
||||
(
|
||||
const CA_SYNC_GID gid,
|
||||
chtype type,
|
||||
@@ -1003,7 +1004,7 @@ int epicsShareAPI ca_sg_array_put
|
||||
*
|
||||
* gid R sync group id
|
||||
*/
|
||||
int epicsShareAPI ca_sg_stat(const CA_SYNC_GID gid);
|
||||
epicsShareFunc int epicsShareAPI ca_sg_stat(const CA_SYNC_GID gid);
|
||||
|
||||
/*
|
||||
* ca_modify_user_name()
|
||||
@@ -1013,7 +1014,7 @@ int epicsShareAPI ca_sg_stat(const CA_SYNC_GID gid);
|
||||
*
|
||||
* pUserName R new user name string copied from this location
|
||||
*/
|
||||
int epicsShareAPI ca_modify_user_name(const char *pUserName);
|
||||
epicsShareFunc int epicsShareAPI ca_modify_user_name(const char *pUserName);
|
||||
|
||||
/*
|
||||
* CA_MODIFY_HOST_NAME()
|
||||
@@ -1023,7 +1024,7 @@ int epicsShareAPI ca_modify_user_name(const char *pUserName);
|
||||
*
|
||||
* pHostName R new host name string copied from this location
|
||||
*/
|
||||
int epicsShareAPI ca_modify_host_name(const char *pHostName);
|
||||
epicsShareFunc int epicsShareAPI ca_modify_host_name(const char *pHostName);
|
||||
|
||||
/*
|
||||
* ca_v42_ok()
|
||||
@@ -1035,14 +1036,14 @@ int epicsShareAPI ca_modify_host_name(const char *pHostName);
|
||||
*
|
||||
* (returns true or false)
|
||||
*/
|
||||
int epicsShareAPI ca_v42_ok(chid chan);
|
||||
epicsShareFunc int epicsShareAPI ca_v42_ok(chid chan);
|
||||
|
||||
/*
|
||||
* ca_version()
|
||||
*
|
||||
* returns the CA version string
|
||||
*/
|
||||
const char * epicsShareAPI ca_version(void);
|
||||
epicsShareFunc const char * epicsShareAPI ca_version(void);
|
||||
|
||||
/*
|
||||
* ca_replace_printf_handler ()
|
||||
@@ -1056,52 +1057,52 @@ const char * epicsShareAPI ca_version(void);
|
||||
* CA prints an error message
|
||||
*/
|
||||
#ifndef CA_DONT_INCLUDE_STDARGH
|
||||
int epicsShareAPI ca_replace_printf_handler (
|
||||
epicsShareFunc int epicsShareAPI ca_replace_printf_handler (
|
||||
int (*ca_printf_func)(const char *pformat, va_list args)
|
||||
);
|
||||
#endif /*CA_DONT_INCLUDE_STDARGH*/
|
||||
|
||||
#else /* CAC_ANSI_FUNC_PROTO */
|
||||
|
||||
int epicsShareAPI ca_task_initialize ();
|
||||
int epicsShareAPI ca_task_exit ();
|
||||
int epicsShareAPI ca_search_and_connect ();
|
||||
int epicsShareAPI ca_build_and_connect ();
|
||||
int epicsShareAPI ca_change_connection_event ();
|
||||
int epicsShareAPI ca_replace_access_rights_event ();
|
||||
int epicsShareAPI ca_add_exception_event ();
|
||||
int epicsShareAPI ca_clear_channel ();
|
||||
int epicsShareAPI ca_array_put ();
|
||||
int epicsShareAPI ca_array_put_callback ();
|
||||
int epicsShareAPI ca_array_get ();
|
||||
int epicsShareAPI ca_array_get_callback ();
|
||||
int epicsShareAPI ca_add_masked_array_event ();
|
||||
int epicsShareAPI ca_clear_event ();
|
||||
int epicsShareAPI ca_pend ();
|
||||
int epicsShareAPI ca_test_io ();
|
||||
int epicsShareAPI ca_flush_io ();
|
||||
void epicsShareAPI ca_signal ();
|
||||
void epicsShareAPI ca_signal_with_file_and_lineno ();
|
||||
char * epicsShareAPI ca_host_name_function ();
|
||||
epicsShareFunc int epicsShareAPI ca_task_initialize ();
|
||||
epicsShareFunc int epicsShareAPI ca_task_exit ();
|
||||
epicsShareFunc int epicsShareAPI ca_search_and_connect ();
|
||||
epicsShareFunc int epicsShareAPI ca_build_and_connect ();
|
||||
epicsShareFunc int epicsShareAPI ca_change_connection_event ();
|
||||
epicsShareFunc int epicsShareAPI ca_replace_access_rights_event ();
|
||||
epicsShareFunc int epicsShareAPI ca_add_exception_event ();
|
||||
epicsShareFunc int epicsShareAPI ca_clear_channel ();
|
||||
epicsShareFunc int epicsShareAPI ca_array_put ();
|
||||
epicsShareFunc int epicsShareAPI ca_array_put_callback ();
|
||||
epicsShareFunc int epicsShareAPI ca_array_get ();
|
||||
epicsShareFunc int epicsShareAPI ca_array_get_callback ();
|
||||
epicsShareFunc int epicsShareAPI ca_add_masked_array_event ();
|
||||
epicsShareFunc int epicsShareAPI ca_clear_event ();
|
||||
epicsShareFunc int epicsShareAPI ca_pend ();
|
||||
epicsShareFunc int epicsShareAPI ca_test_io ();
|
||||
epicsShareFunc int epicsShareAPI ca_flush_io ();
|
||||
epicsShareFunc void epicsShareAPI ca_signal ();
|
||||
epicsShareFunc void epicsShareAPI ca_signal_with_file_and_lineno ();
|
||||
epicsShareFunc char * epicsShareAPI ca_host_name_function ();
|
||||
typedef void CAFDHANDLER();
|
||||
int epicsShareAPI ca_add_fd_registration();
|
||||
int epicsShareAPI ca_replace_printf_handler ();
|
||||
int epicsShareAPI ca_sg_create();
|
||||
int epicsShareAPI ca_sg_delete();
|
||||
int epicsShareAPI ca_sg_block();
|
||||
int epicsShareAPI ca_sg_test();
|
||||
int epicsShareAPI ca_sg_reset();
|
||||
int epicsShareAPI ca_sg_array_get();
|
||||
int epicsShareAPI ca_sg_array_put();
|
||||
int epicsShareAPI ca_sg_stat();
|
||||
int epicsShareAPI ca_modify_user_name();
|
||||
int epicsShareAPI ca_modify_host_name();
|
||||
int epicsShareAPI ca_v42_ok();
|
||||
char * epicsShareAPI ca_version();
|
||||
epicsShareFunc int epicsShareAPI ca_add_fd_registration();
|
||||
epicsShareFunc int epicsShareAPI ca_replace_printf_handler ();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_create();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_delete();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_block();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_test();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_reset();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_array_get();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_array_put();
|
||||
epicsShareFunc int epicsShareAPI ca_sg_stat();
|
||||
epicsShareFunc int epicsShareAPI ca_modify_user_name();
|
||||
epicsShareFunc int epicsShareAPI ca_modify_host_name();
|
||||
epicsShareFunc int epicsShareAPI ca_v42_ok();
|
||||
epicsShareFunc char * epicsShareAPI ca_version();
|
||||
#ifdef vxWorks
|
||||
int epicsShareAPI ca_channel_status()
|
||||
int ca_import();
|
||||
int ca_import_cancel();
|
||||
epicsShareFunc int epicsShareAPI ca_channel_status()
|
||||
epicsShareFunc int epicsShareAPI ca_import();
|
||||
epicsShareFunc int epicsShareAPI ca_import_cancel();
|
||||
#endif
|
||||
|
||||
#endif /* CAC_ANSI_FUNC_PROTO */
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
#ifndef INCLcaerrh
|
||||
#define INCLcaerrh
|
||||
|
||||
#include <shareLib.h>
|
||||
#include <epicsTypes.h>
|
||||
#include "shareLib.h"
|
||||
#include "epicsTypes.h"
|
||||
|
||||
#ifndef HDRVERSIONID
|
||||
# define HDRVERSIONID(NAME,VERS)
|
||||
@@ -213,9 +213,19 @@ READONLY char *ca_message_text[]
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
READONLY char * epicsShareAPI ca_message(long ca_status);
|
||||
#else /* __STDC__ */
|
||||
#ifdef __STDC__
|
||||
#define CAERR_USE_FUNC_PROTO
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifndef CAERR_USE_FUNC_PROTO
|
||||
#define CAERR_USE_FUNC_PROTO
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CAERR_USE_FUNC_PROTO
|
||||
epicsShareFunc READONLY char * epicsShareAPI ca_message(long ca_status);
|
||||
#else /* CAERR_USE_FUNC_PROTO */
|
||||
READONLY char *ca_message();
|
||||
#endif
|
||||
|
||||
|
||||
141
src/ca/catime.c
141
src/ca/catime.c
@@ -12,9 +12,11 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <cadef.h>
|
||||
#include "epicsAssert.h"
|
||||
#include "cadef.h"
|
||||
|
||||
#ifndef LOCAL
|
||||
#define LOCAL static
|
||||
@@ -36,7 +38,11 @@
|
||||
#define NELEMENTS(A) (sizeof (A) / sizeof ((A) [0]))
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
#define ITERATION_COUNT 1000
|
||||
#else
|
||||
#define ITERATION_COUNT 10000
|
||||
#endif
|
||||
|
||||
#define WAIT_FOR_ACK
|
||||
|
||||
@@ -50,7 +56,9 @@ typedef struct testItem {
|
||||
|
||||
ti itemList[ITERATION_COUNT];
|
||||
|
||||
int catime (char *channelName);
|
||||
enum appendNumberFlag {appendNumber, dontAppendNumber};
|
||||
|
||||
int catime (char *channelName, enum appendNumberFlag appNF);
|
||||
|
||||
typedef void tf (ti *pItems, unsigned iterations, unsigned *pInlineIter);
|
||||
|
||||
@@ -59,8 +67,11 @@ LOCAL void test (
|
||||
unsigned iterations
|
||||
);
|
||||
|
||||
LOCAL void printSearchStat(unsigned iterations);
|
||||
|
||||
LOCAL tf test_pend;
|
||||
LOCAL tf test_search;
|
||||
LOCAL tf test_sync_search;
|
||||
LOCAL tf test_free;
|
||||
LOCAL tf test_wait;
|
||||
LOCAL tf test_put;
|
||||
@@ -78,13 +89,19 @@ int main(int argc, char **argv)
|
||||
{
|
||||
char *pname;
|
||||
|
||||
if(argc == 2){
|
||||
pname = argv[1];
|
||||
catime(pname);
|
||||
if(argc <= 1 || argc>3){
|
||||
printf("usage: %s <channel name> [<if 2nd arg present append number to pv name>]\n",
|
||||
argv[0]);
|
||||
return -1;
|
||||
}
|
||||
else{
|
||||
printf("usage: %s <channel name>\n", argv[0]);
|
||||
return -1;
|
||||
pname = argv[1];
|
||||
if (argc==3) {
|
||||
catime(pname, appendNumber);
|
||||
}
|
||||
else {
|
||||
catime(pname, dontAppendNumber);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -94,25 +111,54 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* catime ()
|
||||
*/
|
||||
int catime (char *channelName)
|
||||
int catime (char *channelName, enum appendNumberFlag appNF)
|
||||
{
|
||||
long i;
|
||||
unsigned strsize;
|
||||
|
||||
SEVCHK (ca_task_initialize(),"Unable to initialize");
|
||||
|
||||
if (appNF==appendNumber) {
|
||||
printf("Testing with %lu channels named %snnn\n",
|
||||
(unsigned long) NELEMENTS(itemList), channelName);
|
||||
}
|
||||
else {
|
||||
printf("Testing with %lu channels named %s\n",
|
||||
(unsigned long) NELEMENTS(itemList), channelName);
|
||||
}
|
||||
|
||||
strsize = sizeof(itemList[i].name)-1;
|
||||
for (i=0; i<NELEMENTS(itemList); i++) {
|
||||
strncpy (
|
||||
itemList[i].name,
|
||||
channelName,
|
||||
strsize);
|
||||
if (appNF==appendNumber) {
|
||||
sprintf(itemList[i].name,"%.*s%lu",
|
||||
(int) (strsize - 15u), channelName, i);
|
||||
}
|
||||
else {
|
||||
strncpy (
|
||||
itemList[i].name,
|
||||
channelName,
|
||||
strsize);
|
||||
}
|
||||
itemList[i].name[strsize]= '\0';
|
||||
itemList[i].count = 1;
|
||||
}
|
||||
#if 0
|
||||
printf ("sync search test\n");
|
||||
assert (100u<=NELEMENTS(itemList));
|
||||
timeIt (test_sync_search, itemList, 100u);
|
||||
printSearchStat(100u);
|
||||
|
||||
printf ("free test\n");
|
||||
timeIt (test_free, itemList, 100u);
|
||||
|
||||
printf ("waiting for the server to reply to free requests...");
|
||||
fflush (stdout);
|
||||
ca_pend_event(1.0);
|
||||
printf ("hopefully done\n");
|
||||
#endif
|
||||
printf ("search test\n");
|
||||
timeIt (test_search, itemList, NELEMENTS(itemList));
|
||||
printSearchStat(NELEMENTS(itemList));
|
||||
|
||||
printf (
|
||||
"channel name=%s, native type=%d, native count=%d\n",
|
||||
@@ -152,6 +198,36 @@ int catime (char *channelName)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* printSearchStat()
|
||||
*/
|
||||
LOCAL void printSearchStat(unsigned iterations)
|
||||
{
|
||||
ti *pi;
|
||||
double X = 0u;
|
||||
double XX = 0u;
|
||||
double max = DBL_MIN;
|
||||
double min = DBL_MAX;
|
||||
double mean;
|
||||
double stdDev;
|
||||
|
||||
for (pi=itemList; pi<&itemList[iterations]; pi++) {
|
||||
double retry = pi->chix->retry;
|
||||
X += retry;
|
||||
XX += retry*retry;
|
||||
if (retry>max) {
|
||||
max = retry;
|
||||
}
|
||||
if (retry<min) {
|
||||
min = retry;
|
||||
}
|
||||
}
|
||||
|
||||
mean = X/iterations;
|
||||
stdDev = sqrt(XX/iterations - mean*mean);
|
||||
printf ("Search tries per chan - mean=%f std dev=%f min=%f max=%f\n",
|
||||
mean, stdDev, min, max);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -196,14 +272,20 @@ void timeIt(
|
||||
assert (status == S_ts_OK);
|
||||
#endif
|
||||
TsDiffAsDouble(&delay,&end_time,&start_time);
|
||||
printf ("Elapsed Per Item = %12.8f sec (%10.1f Items per sec)\n",
|
||||
delay/(iterations*inlineIter),
|
||||
(iterations*inlineIter)/delay);
|
||||
if (delay>0.0) {
|
||||
printf ("Elapsed Per Item = %12.8f sec (%10.1f Items per sec)\n",
|
||||
delay/(iterations*inlineIter),
|
||||
(iterations*inlineIter)/delay);
|
||||
}
|
||||
else {
|
||||
printf ("Elapsed Per Item = %12.8f sec\n",
|
||||
delay/(iterations*inlineIter));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* test_search ()
|
||||
* test_pend()
|
||||
*/
|
||||
LOCAL void test_pend(
|
||||
ti *pItems,
|
||||
@@ -264,6 +346,31 @@ unsigned *pInlineIter
|
||||
*pInlineIter = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* test_sync_search()
|
||||
*/
|
||||
LOCAL void test_sync_search(
|
||||
ti *pItems,
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
)
|
||||
{
|
||||
ti *pi;
|
||||
int status;
|
||||
|
||||
for (pi=pItems; pi<&pItems[iterations]; pi++) {
|
||||
status = ca_search (
|
||||
pi->name,
|
||||
&pi->chix);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_pend_io(0.0);
|
||||
SEVCHK (status, NULL);
|
||||
}
|
||||
|
||||
*pInlineIter = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* test_free ()
|
||||
|
||||
665
src/ca/conn.c
665
src/ca/conn.c
@@ -30,6 +30,12 @@
|
||||
/* (dont send all chans in a block) */
|
||||
/* */
|
||||
/* $Log$
|
||||
* Revision 1.38 1997/04/10 19:26:09 jhill
|
||||
* asynch connect, faster connect, ...
|
||||
*
|
||||
* Revision 1.37 1996/11/02 00:50:46 jhill
|
||||
* many pc port, const in API, and other changes
|
||||
*
|
||||
* Revision 1.36 1996/09/16 16:35:22 jhill
|
||||
* local exceptions => exception handler
|
||||
*
|
||||
@@ -63,22 +69,24 @@ LOCAL void logRetryInterval(char *pFN, unsigned lineno);
|
||||
#define LOGRETRYINTERVAL
|
||||
#endif
|
||||
|
||||
LOCAL void retrySearchRequest(int silent);
|
||||
LOCAL void retrySearchRequest();
|
||||
LOCAL unsigned bhtHashIP(const struct sockaddr_in *pina);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* MANAGE_CONN
|
||||
*
|
||||
* retry disconnected channels
|
||||
* manages
|
||||
* o retry of disconnected channels
|
||||
* o connection heart beats
|
||||
*
|
||||
*
|
||||
*/
|
||||
void manage_conn(int silent)
|
||||
void manage_conn()
|
||||
{
|
||||
IIU *piiu;
|
||||
ca_real delay;
|
||||
long idelay;
|
||||
|
||||
/*
|
||||
* prevent recursion
|
||||
@@ -98,7 +106,7 @@ void manage_conn(int silent)
|
||||
piiu;
|
||||
piiu = (IIU *) piiu->node.next){
|
||||
|
||||
if (piiu == piiuCast || !piiu->conn_up) {
|
||||
if (piiu==piiuCast || piiu->state!=iiu_connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -178,7 +186,7 @@ void manage_conn(int silent)
|
||||
/*
|
||||
* Stop here if there are not any disconnected channels
|
||||
*/
|
||||
if(!piiuCast) {
|
||||
if (!piiuCast) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
}
|
||||
@@ -187,51 +195,21 @@ void manage_conn(int silent)
|
||||
return;
|
||||
}
|
||||
|
||||
if(ca_static->ca_conn_next_retry.tv_sec == CA_CURRENT_TIME.tv_sec &&
|
||||
ca_static->ca_conn_next_retry.tv_usec == CA_CURRENT_TIME.tv_usec){
|
||||
ca_static->ca_conn_next_retry = ca_static->currentTime;
|
||||
LOGRETRYINTERVAL
|
||||
}
|
||||
|
||||
delay = cac_time_diff (
|
||||
&ca_static->ca_conn_next_retry,
|
||||
&ca_static->currentTime);
|
||||
|
||||
if (delay > 0.0) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* the retry sequence number
|
||||
* (increments once all channels have received this
|
||||
* the retry sequence number if we have tried a reasonable
|
||||
* number of times and if the retry delay has expired
|
||||
*
|
||||
* (search_retry increments once all channels have received this
|
||||
* number of tries)
|
||||
*/
|
||||
if (ca_static->ca_search_retry >= MAXCONNTRIES) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
if (delay <= 0.0 && ca_static->ca_search_retry < MAXCONNTRIES) {
|
||||
retrySearchRequest ();
|
||||
}
|
||||
|
||||
retrySearchRequest (silent);
|
||||
|
||||
/*
|
||||
* set the retry interval
|
||||
*/
|
||||
assert(ca_static->ca_search_retry < CHAR_BIT*sizeof(idelay));
|
||||
idelay = 1;
|
||||
idelay = idelay << ca_static->ca_search_retry;
|
||||
delay = idelay * CA_RECAST_DELAY; /* sec */
|
||||
delay = min (CA_RECAST_PERIOD, delay);
|
||||
idelay = (long) delay;
|
||||
ca_static->ca_conn_retry_delay.tv_sec = idelay;
|
||||
ca_static->ca_conn_retry_delay.tv_usec =
|
||||
(long) ((delay-idelay)*USEC_PER_SEC);
|
||||
ca_static->ca_conn_next_retry =
|
||||
cac_time_sum (
|
||||
&ca_static->currentTime,
|
||||
&ca_static->ca_conn_retry_delay);
|
||||
LOGRETRYINTERVAL
|
||||
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
}
|
||||
|
||||
@@ -239,91 +217,228 @@ void manage_conn(int silent)
|
||||
/*
|
||||
* retrySearchRequest ()
|
||||
*/
|
||||
LOCAL void retrySearchRequest (int silent)
|
||||
LOCAL void retrySearchRequest ()
|
||||
{
|
||||
ELLLIST channelsSent;
|
||||
ciu chix;
|
||||
unsigned min_retry_num;
|
||||
unsigned retry_cnt = 0;
|
||||
unsigned retry_cnt_no_handler = 0;
|
||||
ciu chan;
|
||||
ciu firstChan;
|
||||
int status;
|
||||
unsigned nSent=0u;
|
||||
|
||||
if (!piiuCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
ellInit (&channelsSent);
|
||||
/*
|
||||
* check to see if there is nothing to do here
|
||||
*/
|
||||
if (ellCount(&piiuCast->chidlist)==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
min_retry_num = MAXCONNTRIES;
|
||||
while ( (chix = (ciu) ellGet (&piiuCast->chidlist)) ) {
|
||||
|
||||
ellAdd (&channelsSent, &chix->node);
|
||||
|
||||
min_retry_num = min (min_retry_num, chix->retry);
|
||||
|
||||
if (chix->retry <= ca_static->ca_search_retry) {
|
||||
|
||||
status = search_msg (chix, DONTREPLY);
|
||||
if (status == ECA_NORMAL) {
|
||||
retry_cnt++;
|
||||
if (!(silent || chix->pConnFunc)) {
|
||||
genLocalExcep (
|
||||
ECA_CHIDNOTFND,
|
||||
(char *)(chix+1));
|
||||
retry_cnt_no_handler++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* increment the retry sequence number
|
||||
*/
|
||||
ca_static->ca_search_retry_seq_no++; /* allowed to roll over */
|
||||
|
||||
/*
|
||||
* if we saw the entire list
|
||||
* dynamically adjust the number of UDP frames per
|
||||
* try depending how many search requests are not
|
||||
* replied to
|
||||
*
|
||||
* This determines how many search request can be
|
||||
* sent together (at the same instant in time).
|
||||
*
|
||||
* The variable ca_static->ca_frames_per_try
|
||||
* determines the number of UDP frames to be sent
|
||||
* each time that retrySearchRequest() is called.
|
||||
* If this value is too high we will waste some
|
||||
* network bandwidth. If it is too low we will
|
||||
* use very little of the incoming UDP message
|
||||
* buffer associated with the server's port and
|
||||
* will therefore take longer to connect. We
|
||||
* initialize ca_static->ca_frames_per_try
|
||||
* to a prime number so that it is less likely that the
|
||||
* same channel is in the last UDP frame
|
||||
* sent every time that this is called (and
|
||||
* potentially discarded by a CA server with
|
||||
* a small UDP input queue).
|
||||
*/
|
||||
if (chix==NULL) {
|
||||
/*
|
||||
* increment the retry sequence number
|
||||
* (only if we get no responses during a sequence)
|
||||
*/
|
||||
if (ca_static->ca_search_retry<MAXCONNTRIES
|
||||
&& ca_static->ca_search_responses==0) {
|
||||
ca_static->ca_search_retry++;
|
||||
}
|
||||
|
||||
/*
|
||||
* increase rapidly if we see better than a 75% success rate
|
||||
*/
|
||||
if (ca_static->ca_search_responses >
|
||||
(ca_static->ca_search_tries-(ca_static->ca_search_tries/4u)) ) {
|
||||
/*
|
||||
* jump to the minimum retry number
|
||||
* double UDP frames per try if we have a good score
|
||||
*/
|
||||
if (ca_static->ca_search_retry<min_retry_num) {
|
||||
ca_static->ca_search_retry = min_retry_num;
|
||||
ca_static->ca_search_responses = 0;
|
||||
if (ca_static->ca_frames_per_try < (UINT_MAX/4u) ) {
|
||||
ca_static->ca_frames_per_try += ca_static->ca_frames_per_try;
|
||||
#ifdef DEBUG
|
||||
printf ("Increasing frame count to %u t=%u r=%u\n",
|
||||
ca_static->ca_frames_per_try, ca_static->ca_search_tries,
|
||||
ca_static->ca_search_responses);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*
|
||||
* if we have less than a 50% success rate then reduce the count gradually
|
||||
*/
|
||||
else if (ca_static->ca_search_responses < (ca_static->ca_search_tries/2u) ) {
|
||||
if (ca_static->ca_frames_per_try>1u) {
|
||||
ca_static->ca_frames_per_try--;
|
||||
#ifdef DEBUG
|
||||
printf ("Decreasing frame count to %u t=%u r=%u\n",
|
||||
ca_static->ca_frames_per_try, ca_static->ca_search_tries,
|
||||
ca_static->ca_search_responses);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return channels sent to main cast IIU's
|
||||
* channel prior to removing the lock
|
||||
*
|
||||
* This reorders the list so that each channel
|
||||
* get a fair chance to connect
|
||||
* a successful search_msg() sends channel to
|
||||
* the end of the list
|
||||
*/
|
||||
ellConcat (&piiuCast->chidlist, &channelsSent);
|
||||
firstChan = chan = (ciu) ellFirst (&piiuCast->chidlist);
|
||||
while (chan) {
|
||||
|
||||
ca_static->ca_min_retry =
|
||||
min(ca_static->ca_min_retry, chan->retry);
|
||||
|
||||
/*
|
||||
* clear counter when we reach the end of the list
|
||||
*
|
||||
* if we are making some progress then
|
||||
* dont increase the delay between search
|
||||
* requests
|
||||
*/
|
||||
if (ca_static->ca_pEndOfBCastList == chan) {
|
||||
if (ca_static->ca_search_responses==0u) {
|
||||
cacSetRetryInterval(ca_static->ca_min_retry+1u);
|
||||
}
|
||||
|
||||
ca_static->ca_min_retry = UINT_MAX;
|
||||
|
||||
/*
|
||||
* increment the retry sequence number
|
||||
* (this prevents the time of the next search
|
||||
* try from being set to the current time if
|
||||
* we are handling a response from an old
|
||||
* search message)
|
||||
*/
|
||||
ca_static->ca_search_retry_seq_no++; /* allowed to roll over */
|
||||
|
||||
/*
|
||||
* so that old search tries will not update the counters
|
||||
*/
|
||||
ca_static->ca_seq_no_at_list_begin = ca_static->ca_search_retry_seq_no;
|
||||
/*
|
||||
* keeps the search try/response counters in bounds
|
||||
* (but keep some of the info from the previous iteration)
|
||||
*/
|
||||
ca_static->ca_search_responses = ca_static->ca_search_responses/16u;
|
||||
ca_static->ca_search_tries = ca_static->ca_search_tries/16u;
|
||||
#ifdef DEBUG
|
||||
printf ("saw end of list\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* this moves the channel to the end of the
|
||||
* list (if successful)
|
||||
*/
|
||||
status = search_msg (chan, DONTREPLY);
|
||||
if (status != ECA_NORMAL) {
|
||||
nSent++;
|
||||
|
||||
if (nSent>=ca_static->ca_frames_per_try) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* flush out the search request buffer
|
||||
*/
|
||||
(*piiuCast->sendBytes)(piiuCast);
|
||||
|
||||
/*
|
||||
* try again
|
||||
*/
|
||||
status = search_msg (chan, DONTREPLY);
|
||||
if (status != ECA_NORMAL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
chan->retrySeqNo = ca_static->ca_search_retry_seq_no;
|
||||
chan = (ciu) ellFirst (&piiuCast->chidlist);
|
||||
|
||||
/*
|
||||
* dont send any of the channels twice within one try
|
||||
*/
|
||||
if (chan==firstChan) {
|
||||
/*
|
||||
* add one to nSent because there may be
|
||||
* one more partial frame to be sent
|
||||
*/
|
||||
nSent++;
|
||||
|
||||
/*
|
||||
* cap ca_static->ca_frames_per_try to
|
||||
* the number of frames required for all of
|
||||
* the unresolved channels
|
||||
*/
|
||||
if (ca_static->ca_frames_per_try>nSent) {
|
||||
ca_static->ca_frames_per_try = nSent;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
ca_static->ca_conn_next_retry =
|
||||
cac_time_sum (
|
||||
&ca_static->currentTime,
|
||||
&ca_static->ca_conn_retry_delay);
|
||||
LOGRETRYINTERVAL
|
||||
#ifdef DEBUG
|
||||
printf("sent %u at cur sec=%u cur usec=%u delay sec=%u delay usec = %u\n",
|
||||
nSent, ca_static->currentTime.tv_sec,
|
||||
ca_static->currentTime.tv_usec,
|
||||
ca_static->ca_conn_retry_delay.tv_sec,
|
||||
ca_static->ca_conn_retry_delay.tv_usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* cacSetRetryInterval()
|
||||
* (sets the interval between search tries)
|
||||
*/
|
||||
void cacSetRetryInterval(unsigned retryNo)
|
||||
{
|
||||
long idelay;
|
||||
ca_real delay;
|
||||
|
||||
/*
|
||||
* LOCK around use of the sprintf buffer
|
||||
* set the retry interval
|
||||
*/
|
||||
if (retry_cnt) {
|
||||
if (!silent && retry_cnt_no_handler) {
|
||||
sprintf (
|
||||
sprintf_buf,
|
||||
"%d channels outstanding",
|
||||
retry_cnt);
|
||||
genLocalExcep (ECA_CHIDRETRY, sprintf_buf);
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
retryNo = min(retryNo, CHAR_BIT*sizeof(idelay)-1);
|
||||
ca_static->ca_search_retry = retryNo;
|
||||
idelay = 1;
|
||||
idelay = idelay << ca_static->ca_search_retry;
|
||||
delay = idelay * CA_RECAST_DELAY; /* sec */
|
||||
delay = min (CA_RECAST_PERIOD, delay);
|
||||
idelay = (long) delay;
|
||||
ca_static->ca_conn_retry_delay.tv_sec = idelay;
|
||||
ca_static->ca_conn_retry_delay.tv_usec =
|
||||
(long) ((delay-idelay)*USEC_PER_SEC);
|
||||
#if 0
|
||||
printf ("new search period is %u sec %u usec\n",
|
||||
ca_static->ca_conn_retry_delay.tv_sec,
|
||||
ca_static->ca_conn_retry_delay.tv_usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +475,7 @@ LOCAL void logRetryInterval(char *pFN, unsigned lineno)
|
||||
/*
|
||||
* MARK_SERVER_AVAILABLE
|
||||
*/
|
||||
void mark_server_available(const struct in_addr *pnet_addr)
|
||||
void mark_server_available(const struct sockaddr_in *pnet_addr)
|
||||
{
|
||||
ciu chan;
|
||||
ca_real currentPeriod;
|
||||
@@ -368,12 +483,6 @@ void mark_server_available(const struct in_addr *pnet_addr)
|
||||
unsigned port;
|
||||
int netChange = FALSE;
|
||||
|
||||
/*
|
||||
* if timers have expired take care of them
|
||||
* before they are reset
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
|
||||
if(!piiuCast){
|
||||
return;
|
||||
}
|
||||
@@ -383,70 +492,131 @@ void mark_server_available(const struct in_addr *pnet_addr)
|
||||
* look for it in the hash table
|
||||
*/
|
||||
pBHE = lookupBeaconInetAddr(pnet_addr);
|
||||
if(pBHE){
|
||||
|
||||
if(!pBHE){
|
||||
/*
|
||||
* if we have seen the beacon before ignore it
|
||||
* (unless there is an unusual change in its period)
|
||||
* wait until 2nd beacon is seen before deciding
|
||||
* if it is a new server (or just the first
|
||||
* time that we have seen a server's beacon
|
||||
* shortly after the program started up)
|
||||
*/
|
||||
createBeaconHashEntry(pnet_addr, TRUE);
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* update time stamp and average period
|
||||
/*
|
||||
* if we have seen the beacon before ignore it
|
||||
* (unless there is an unusual change in its period)
|
||||
*/
|
||||
|
||||
/*
|
||||
* compute the beacon period (if we have seen at least two beacons)
|
||||
*/
|
||||
if (pBHE->timeStamp.tv_sec==0 && pBHE->timeStamp.tv_usec==0) {
|
||||
/*
|
||||
* this is the 1st beacon seen
|
||||
* (nothing to do but set the beacon time stamp)
|
||||
*/
|
||||
pBHE->timeStamp = ca_static->currentTime;
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
currentPeriod = cac_time_diff (
|
||||
&ca_static->currentTime,
|
||||
&pBHE->timeStamp);
|
||||
/*
|
||||
* update the average
|
||||
*/
|
||||
pBHE->averagePeriod += currentPeriod;
|
||||
pBHE->averagePeriod /= 2.0;
|
||||
pBHE->timeStamp = ca_static->currentTime;
|
||||
|
||||
if ((currentPeriod/4.0)>=pBHE->averagePeriod) {
|
||||
if (pBHE->averagePeriod<0.0) {
|
||||
ca_real totRunningTime;
|
||||
/*
|
||||
* this is the 2nd beacon seen
|
||||
* (init the average period)
|
||||
*/
|
||||
totRunningTime = cac_time_diff (
|
||||
&pBHE->timeStamp,
|
||||
&ca_static->programBeginTime);
|
||||
pBHE->averagePeriod = currentPeriod;
|
||||
if (currentPeriod<=totRunningTime) {
|
||||
/*
|
||||
* this is a beacon seen for the first
|
||||
* time because the host was reinitialized
|
||||
* or because a network link was restored
|
||||
*
|
||||
* this is not a beacon seen for the first
|
||||
* time just after program init
|
||||
*/
|
||||
netChange = TRUE;
|
||||
#ifdef DEBUG
|
||||
ca_printf(
|
||||
"net resume seen %x cur=%d avg=%d\n",
|
||||
pnet_addr->s_addr,
|
||||
currentPeriod,
|
||||
pBHE->averagePeriod);
|
||||
ca_printf(
|
||||
"new server at %x cur=%f avg=%f\n",
|
||||
pnet_addr->sin_addr.s_addr,
|
||||
currentPeriod,
|
||||
pBHE->averagePeriod);
|
||||
#endif
|
||||
netChange = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* this is any other beacon
|
||||
* (update a running average)
|
||||
*/
|
||||
pBHE->averagePeriod += currentPeriod;
|
||||
pBHE->averagePeriod /= 2.0;
|
||||
|
||||
/*
|
||||
* is this an IOC seen because of a restored
|
||||
* network segment
|
||||
*/
|
||||
if ((currentPeriod/4.0)>=pBHE->averagePeriod) {
|
||||
#ifdef DEBUG
|
||||
ca_printf(
|
||||
"net resume seen %x cur=%f avg=%f\n",
|
||||
pnet_addr->sin_addr.s_addr,
|
||||
currentPeriod,
|
||||
pBHE->averagePeriod);
|
||||
#endif
|
||||
netChange = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* is this an IOC seen because of an IOC reboot
|
||||
*/
|
||||
if ((pBHE->averagePeriod/2.0)>=currentPeriod) {
|
||||
#ifdef DEBUG
|
||||
ca_printf(
|
||||
"reboot seen %x cur=%f avg=%f\n",
|
||||
pnet_addr->sin_addr.s_addr,
|
||||
currentPeriod,
|
||||
pBHE->averagePeriod);
|
||||
#endif
|
||||
netChange = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pBHE->averagePeriod/2.0)>=currentPeriod) {
|
||||
#ifdef DEBUG
|
||||
ca_printf(
|
||||
"reboot seen %x cur=%d avg=%d\n",
|
||||
pnet_addr->s_addr,
|
||||
currentPeriod,
|
||||
pBHE->averagePeriod);
|
||||
#endif
|
||||
netChange = TRUE;
|
||||
}
|
||||
if(pBHE->piiu){
|
||||
pBHE->piiu->timeAtLastRecv = ca_static->currentTime;
|
||||
}
|
||||
if(!netChange){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* update beacon time stamp
|
||||
*/
|
||||
pBHE->timeStamp = ca_static->currentTime;
|
||||
}
|
||||
else{
|
||||
pBHE = createBeaconHashEntry(pnet_addr);
|
||||
if(!pBHE){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This part is essential since many machines
|
||||
* might have channels in a disconnected state which
|
||||
* update state of health for active virtual circuits
|
||||
*/
|
||||
if(pBHE->piiu){
|
||||
pBHE->piiu->timeAtLastRecv = ca_static->currentTime;
|
||||
}
|
||||
|
||||
if(!netChange){
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This part is needed when many machines
|
||||
* have channels in a disconnected state that
|
||||
* dont exist anywhere on the network. This insures
|
||||
* that we dont have many CA clients synchronously
|
||||
* flooding the network with broadcasts.
|
||||
* flooding the network with broadcasts (and swamping
|
||||
* out requests for valid channels).
|
||||
*
|
||||
* I fetch the local port number and use the low order bits
|
||||
* as a pseudo random delay to prevent every one
|
||||
@@ -487,20 +657,16 @@ void mark_server_available(const struct in_addr *pnet_addr)
|
||||
ca_static->ca_conn_next_retry = next;
|
||||
LOGRETRYINTERVAL
|
||||
}
|
||||
idelay = (long) CA_RECAST_DELAY;
|
||||
ca_static->ca_conn_retry_delay.tv_sec = idelay;
|
||||
ca_static->ca_conn_retry_delay.tv_usec =
|
||||
(long) ((CA_RECAST_DELAY-idelay) * USEC_PER_SEC);
|
||||
ca_static->ca_search_retry = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set retry count of all disconnected channels
|
||||
* to zero
|
||||
*/
|
||||
cacSetRetryInterval(0u);
|
||||
chan = (ciu) ellFirst(&piiuCast->chidlist);
|
||||
while (chan) {
|
||||
chan->retry = 0;
|
||||
chan->retry = 0u;
|
||||
chan = (ciu) ellNext (&chan->node);
|
||||
}
|
||||
|
||||
@@ -513,20 +679,17 @@ void mark_server_available(const struct in_addr *pnet_addr)
|
||||
*
|
||||
* LOCK must be applied
|
||||
*/
|
||||
bhe *createBeaconHashEntry(const struct in_addr *pnet_addr)
|
||||
bhe *createBeaconHashEntry(const struct sockaddr_in *pina, unsigned sawBeacon)
|
||||
{
|
||||
bhe *pBHE;
|
||||
unsigned index;
|
||||
|
||||
pBHE = lookupBeaconInetAddr(pnet_addr);
|
||||
pBHE = lookupBeaconInetAddr(pina);
|
||||
if(pBHE){
|
||||
return pBHE;
|
||||
}
|
||||
|
||||
index = ntohl(pnet_addr->s_addr);
|
||||
index &= BHT_INET_ADDR_MASK;
|
||||
|
||||
assert(index<NELEMENTS(ca_static->ca_beaconHash));
|
||||
index = bhtHashIP(pina);
|
||||
|
||||
pBHE = (bhe *)calloc(1,sizeof(*pBHE));
|
||||
if(!pBHE){
|
||||
@@ -534,19 +697,38 @@ bhe *createBeaconHashEntry(const struct in_addr *pnet_addr)
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ca_printf("new IOC %x\n", pnet_addr->s_addr);
|
||||
ca_printf("new beacon at %x %u\n", pina->sin_addr.s_addr, pina->sin_port);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* store the inet address
|
||||
*/
|
||||
pBHE->inetAddr = *pnet_addr;
|
||||
pBHE->inetAddr = *pina;
|
||||
|
||||
/*
|
||||
* start the average at zero
|
||||
* set average to -1.0 so that when the next beacon
|
||||
* occurs we can distinguish between:
|
||||
* o new server
|
||||
* o existing server's beacon we are seeing
|
||||
* for the first time shortly after program
|
||||
* start up
|
||||
*/
|
||||
pBHE->averagePeriod = 0.0;
|
||||
pBHE->timeStamp = ca_static->currentTime;
|
||||
pBHE->averagePeriod = -1.0;
|
||||
|
||||
/*
|
||||
* if creating this in response to a search reply
|
||||
* and not in response to a beacon then sawBeacon
|
||||
* is false and we set the beacon time stamp to
|
||||
* zero (so we can correctly compute the period
|
||||
beacon at * between the 1st and 2nd beacons)
|
||||
*/
|
||||
if (sawBeacon) {
|
||||
pBHE->timeStamp = ca_static->currentTime;
|
||||
}
|
||||
else {
|
||||
pBHE->timeStamp.tv_sec = 0;
|
||||
pBHE->timeStamp.tv_usec = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* install in the hash table
|
||||
@@ -563,19 +745,17 @@ bhe *createBeaconHashEntry(const struct in_addr *pnet_addr)
|
||||
*
|
||||
* LOCK must be applied
|
||||
*/
|
||||
bhe *lookupBeaconInetAddr (const struct in_addr *pnet_addr)
|
||||
bhe *lookupBeaconInetAddr (const struct sockaddr_in *pina)
|
||||
{
|
||||
bhe *pBHE;
|
||||
unsigned index;
|
||||
|
||||
index = ntohl(pnet_addr->s_addr);
|
||||
index &= BHT_INET_ADDR_MASK;
|
||||
|
||||
assert(index<NELEMENTS(ca_static->ca_beaconHash));
|
||||
index = bhtHashIP(pina);
|
||||
|
||||
pBHE = ca_static->ca_beaconHash[index];
|
||||
while(pBHE){
|
||||
if(pBHE->inetAddr.s_addr == pnet_addr->s_addr){
|
||||
while (pBHE) {
|
||||
if ( pBHE->inetAddr.sin_addr.s_addr == pina->sin_addr.s_addr &&
|
||||
pBHE->inetAddr.sin_port == pina->sin_port) {
|
||||
break;
|
||||
}
|
||||
pBHE = pBHE->pNext;
|
||||
@@ -590,21 +770,19 @@ bhe *lookupBeaconInetAddr (const struct in_addr *pnet_addr)
|
||||
*
|
||||
* LOCK must be applied
|
||||
*/
|
||||
void removeBeaconInetAddr (const struct in_addr *pnet_addr)
|
||||
void removeBeaconInetAddr (const struct sockaddr_in *pina)
|
||||
{
|
||||
bhe *pBHE;
|
||||
bhe **ppBHE;
|
||||
unsigned index;
|
||||
|
||||
index = ntohl (pnet_addr->s_addr);
|
||||
index &= BHT_INET_ADDR_MASK;
|
||||
|
||||
assert (index<NELEMENTS(ca_static->ca_beaconHash));
|
||||
index = bhtHashIP(pina);
|
||||
|
||||
ppBHE = &ca_static->ca_beaconHash[index];
|
||||
pBHE = *ppBHE;
|
||||
while (pBHE) {
|
||||
if (pBHE->inetAddr.s_addr == pnet_addr->s_addr) {
|
||||
if ( pBHE->inetAddr.sin_addr.s_addr == pina->sin_addr.s_addr &&
|
||||
pBHE->inetAddr.sin_port == pina->sin_port) {
|
||||
*ppBHE = pBHE->pNext;
|
||||
free (pBHE);
|
||||
return;
|
||||
@@ -615,13 +793,34 @@ void removeBeaconInetAddr (const struct in_addr *pnet_addr)
|
||||
assert (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* bhtHashIP()
|
||||
*/
|
||||
LOCAL unsigned bhtHashIP(const struct sockaddr_in *pina)
|
||||
{
|
||||
unsigned index;
|
||||
|
||||
#if BHT_INET_ADDR_MASK != 0xff
|
||||
# error BHT_INET_ADDR_MASK changed - recode this routine !
|
||||
#endif
|
||||
|
||||
index = pina->sin_addr.s_addr;
|
||||
index ^= pina->sin_port;
|
||||
index = (index>>16u) ^ index;
|
||||
index = (index>>8u) ^ index;
|
||||
index &= BHT_INET_ADDR_MASK;
|
||||
assert(index<NELEMENTS(ca_static->ca_beaconHash));
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* freeBeaconHash()
|
||||
*
|
||||
* LOCK must be applied
|
||||
*/
|
||||
void freeBeaconHash(struct ca_static *ca_temp)
|
||||
void freeBeaconHash(struct CA_STATIC *ca_temp)
|
||||
{
|
||||
bhe *pBHE;
|
||||
bhe **ppBHE;
|
||||
@@ -643,3 +842,89 @@ void freeBeaconHash(struct ca_static *ca_temp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* retryPendingClaims()
|
||||
*
|
||||
* This assumes that all channels with claims pending are at the
|
||||
* front of the list (and that the channel is moved to the end of
|
||||
* the list when a claim message has been sent for it)
|
||||
*
|
||||
* We send claim messages here until the outgoing message buffer
|
||||
* will not accept any more messages
|
||||
*/
|
||||
void retryPendingClaims(IIU *piiu)
|
||||
{
|
||||
chid chan;
|
||||
int status;
|
||||
|
||||
while ( (chan= (ciu) ellFirst (&piiu->chidlist)) ) {
|
||||
if (!chan->claimPending) {
|
||||
piiu->claimsPending = FALSE;
|
||||
return;
|
||||
}
|
||||
status = issue_claim_channel(chan);
|
||||
if (status!=ECA_NORMAL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add chan to IIU and guarantee that
|
||||
* one chan on the B cast IIU list is pointed to by
|
||||
* ca_pEndOfBCastList
|
||||
*/
|
||||
void addToChanList(ciu chan, IIU *piiu)
|
||||
{
|
||||
if (piiu==piiuCast) {
|
||||
/*
|
||||
* add to the beginning of the list so that search requests for
|
||||
* this channel will be sent first (since the retry count is zero)
|
||||
*/
|
||||
if (ellCount(&piiu->chidlist)==0) {
|
||||
ca_static->ca_pEndOfBCastList = chan;
|
||||
}
|
||||
/*
|
||||
* add to the front of the list so that
|
||||
* search requests for new channels will be sent first
|
||||
*/
|
||||
chan->retry = 0u;
|
||||
ellInsert(&piiu->chidlist, NULL, &chan->node);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* add to the beginning of the list until we
|
||||
* have sent the claim message (after which we
|
||||
* move it to the end of the list)
|
||||
*/
|
||||
chan->claimPending = TRUE;
|
||||
ellInsert(&piiu->chidlist, NULL, &chan->node);
|
||||
}
|
||||
chan->piiu = piiu;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove chan from B-cast IIU and guarantee that
|
||||
* one chan on the list is pointed to by
|
||||
* ca_pEndOfBCastList
|
||||
*/
|
||||
void removeFromChanList(ciu chan)
|
||||
{
|
||||
IIU *piiu = (IIU *) chan->piiu;
|
||||
|
||||
if (piiu==piiuCast) {
|
||||
if (ca_static->ca_pEndOfBCastList == chan) {
|
||||
if (ellPrevious(&chan->node)) {
|
||||
ca_static->ca_pEndOfBCastList = (ciu)
|
||||
ellPrevious(&chan->node);
|
||||
}
|
||||
else {
|
||||
ca_static->ca_pEndOfBCastList = (ciu)
|
||||
ellLast(&piiu->chidlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
ellDelete(&piiu->chidlist, &chan->node);
|
||||
chan->piiu=NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,8 +91,11 @@ LOCAL CACVRTFUNC cvrt_ctrl_char;
|
||||
LOCAL CACVRTFUNC cvrt_ctrl_long;
|
||||
LOCAL CACVRTFUNC cvrt_ctrl_double;
|
||||
|
||||
LOCAL CACVRTFUNC cvrt_put_ackt;
|
||||
LOCAL CACVRTFUNC cvrt_stsack_string;
|
||||
|
||||
/* cvrt is (array of) (pointer to) (function returning) int */
|
||||
CACVRTFUNC *cac_dbr_cvrt[]
|
||||
epicsShareDef CACVRTFUNC *cac_dbr_cvrt[]
|
||||
=
|
||||
{
|
||||
cvrt_string,
|
||||
@@ -133,7 +136,11 @@ CACVRTFUNC *cac_dbr_cvrt[]
|
||||
cvrt_ctrl_enum,
|
||||
cvrt_ctrl_char,
|
||||
cvrt_ctrl_long,
|
||||
cvrt_ctrl_double
|
||||
cvrt_ctrl_double,
|
||||
|
||||
cvrt_put_ackt,
|
||||
cvrt_put_ackt, /* DBR_PUT_ACKS identical to DBR_PUT_ACKT */
|
||||
cvrt_stsack_string
|
||||
};
|
||||
|
||||
|
||||
@@ -1381,6 +1388,76 @@ unsigned long num /* number of values */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cvrt_put_ackt()
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL void cvrt_put_ackt(
|
||||
void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
dbr_put_ackt_t *pSrc = s;
|
||||
dbr_put_ackt_t *pDest = d;
|
||||
unsigned long i;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
*pDest = dbr_ntohs( *pSrc );
|
||||
/*
|
||||
* dont increment these inside the MACRO
|
||||
*/
|
||||
pDest++;
|
||||
pSrc++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** cvrt_stsack_string(s,d)
|
||||
** struct dbr_stsack_string *s pointer to source struct
|
||||
** struct dbr_stsack_string *d pointer to destination struct
|
||||
** int encode; boolean, if true vax to ieee
|
||||
** else ieee to vax
|
||||
**
|
||||
** converts fields of struct in HOST format to NET format
|
||||
** or
|
||||
** converts fields of struct in NET format to fields with HOST
|
||||
** format;
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_stsack_string(
|
||||
void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_stsack_string *pSrc = s;
|
||||
struct dbr_stsack_string *pDest = d;
|
||||
|
||||
/* convert ieee to vax format or vax to ieee */
|
||||
pDest->status = dbr_ntohs(pSrc->status);
|
||||
pDest->severity = dbr_ntohs(pSrc->severity);
|
||||
pDest->ackt = dbr_ntohs(pSrc->ackt);
|
||||
pDest->acks = dbr_ntohs(pSrc->acks);
|
||||
|
||||
/* convert "in place" -> nothing else to do */
|
||||
if (s == d)
|
||||
return;
|
||||
|
||||
if (num == 1) /* if single value */
|
||||
strcpy(pDest->value, pSrc->value);
|
||||
else
|
||||
memcpy(pDest->value, pSrc->value, (MAX_STRING_SIZE * num));
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if defined(CA_FLOAT_MIT)
|
||||
/************************************************************************/
|
||||
@@ -1673,7 +1750,7 @@ void dbr_ntohd (dbr_double_t *IEEEnet, dbr_double_t *IEEEhost)
|
||||
*/
|
||||
tmp = pNet[0];
|
||||
pHost[0] = dbr_ntohl (pNet[1]);
|
||||
pHost[1] = dbr_htonl (tmp);
|
||||
pHost[1] = dbr_ntohl (tmp);
|
||||
#else
|
||||
*IEEEhost = *IEEEnet;
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#include <cadef.h>
|
||||
#include <dbDefs.h>
|
||||
#include "cadef.h"
|
||||
#include "dbDefs.h"
|
||||
|
||||
void event_handler(struct event_handler_args args);
|
||||
int main(int argc, char **argv);
|
||||
|
||||
@@ -37,7 +37,6 @@ static char *sccsId = "@(#) $Id$";
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FLOW CONTROL
|
||||
@@ -47,49 +46,54 @@ static char *sccsId = "@(#) $Id$";
|
||||
* suppress monitors if we are behind
|
||||
* (an update is sent when we catch up)
|
||||
*/
|
||||
void flow_control(struct ioc_in_use *piiu)
|
||||
|
||||
void flow_control_on(struct ioc_in_use *piiu)
|
||||
{
|
||||
unsigned nbytes;
|
||||
int status;
|
||||
int status;
|
||||
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* use of the additional system call here does not
|
||||
* seem to slow things down appreciably
|
||||
*/
|
||||
status = socket_ioctl(piiu->sock_chan,
|
||||
FIONREAD,
|
||||
&nbytes);
|
||||
if (status < 0) {
|
||||
TAG_CONN_DOWN(piiu);
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* I wish to avoid going into flow control however
|
||||
* I prefer to avoid going into flow control
|
||||
* as this impacts the performance of batched fetches
|
||||
*/
|
||||
if (nbytes) {
|
||||
piiu->contiguous_msg_count++;
|
||||
if (!piiu->client_busy)
|
||||
if (piiu->contiguous_msg_count >
|
||||
MAX_CONTIGUOUS_MSG_COUNT) {
|
||||
if (piiu->contiguous_msg_count >= MAX_CONTIGUOUS_MSG_COUNT) {
|
||||
if (!piiu->client_busy) {
|
||||
status = ca_busy_message(piiu);
|
||||
if (status==ECA_NORMAL) {
|
||||
assert(ca_static->ca_number_iiu_in_fc<UINT_MAX);
|
||||
ca_static->ca_number_iiu_in_fc++;
|
||||
piiu->client_busy = TRUE;
|
||||
ca_busy_message(piiu);
|
||||
# if defined(DEBUG)
|
||||
printf("fc on\n");
|
||||
# endif
|
||||
}
|
||||
} else {
|
||||
piiu->contiguous_msg_count = 0;
|
||||
if (piiu->client_busy) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
piiu->contiguous_msg_count++;
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
void flow_control_off(struct ioc_in_use *piiu)
|
||||
{
|
||||
int status;
|
||||
|
||||
LOCK;
|
||||
|
||||
piiu->contiguous_msg_count = 0;
|
||||
if (piiu->client_busy) {
|
||||
status = ca_ready_message(piiu);
|
||||
if (status==ECA_NORMAL) {
|
||||
assert(ca_static->ca_number_iiu_in_fc>0u);
|
||||
ca_static->ca_number_iiu_in_fc--;
|
||||
piiu->client_busy = FALSE;
|
||||
# if defined(DEBUG)
|
||||
printf("fc off\n");
|
||||
# endif
|
||||
ca_ready_message(piiu);
|
||||
piiu->client_busy = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
492
src/ca/iocinf.c
492
src/ca/iocinf.c
@@ -47,6 +47,18 @@
|
||||
/* address in use so that test works on UNIX */
|
||||
/* kernels that support multicast */
|
||||
/* $Log$
|
||||
* Revision 1.70 1997/05/05 04:44:39 jhill
|
||||
* socket buf matches CA buf size, and pushPending flag added
|
||||
*
|
||||
* Revision 1.69 1997/04/23 17:05:05 jhill
|
||||
* pc port changes
|
||||
*
|
||||
* Revision 1.68 1997/04/10 19:26:14 jhill
|
||||
* asynch connect, faster connect, ...
|
||||
*
|
||||
* Revision 1.67 1997/01/08 22:48:42 jhill
|
||||
* improved message
|
||||
*
|
||||
* Revision 1.66 1996/11/02 00:50:53 jhill
|
||||
* many pc port, const in API, and other changes
|
||||
*
|
||||
@@ -100,13 +112,17 @@ static char *sccsId = "@(#) $Id$";
|
||||
#include "net_convert.h"
|
||||
|
||||
LOCAL void tcp_recv_msg(struct ioc_in_use *piiu);
|
||||
LOCAL void cac_connect_iiu(struct ioc_in_use *piiu);
|
||||
LOCAL void cac_set_iiu_non_blocking (struct ioc_in_use *piiu);
|
||||
LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu);
|
||||
LOCAL void cac_udp_send_msg_piiu(struct ioc_in_use *piiu);
|
||||
LOCAL void udp_recv_msg(struct ioc_in_use *piiu);
|
||||
LOCAL void ca_process_tcp(struct ioc_in_use *piiu);
|
||||
LOCAL void ca_process_udp(struct ioc_in_use *piiu);
|
||||
LOCAL void cacRingBufferInit(struct ca_buffer *pBuf, unsigned long size);
|
||||
LOCAL char *getToken(char **ppString);
|
||||
LOCAL void ca_process_tcp(struct ioc_in_use *piiu);
|
||||
LOCAL void ca_process_udp(struct ioc_in_use *piiu);
|
||||
LOCAL void cacRingBufferInit(struct ca_buffer *pBuf,
|
||||
unsigned long size);
|
||||
LOCAL char *getToken(const char **ppString, char *pBuf,
|
||||
unsigned bufSize);
|
||||
LOCAL void close_ioc (IIU *piiu);
|
||||
|
||||
|
||||
@@ -120,9 +136,8 @@ LOCAL void close_ioc (IIU *piiu);
|
||||
*
|
||||
*/
|
||||
int alloc_ioc(
|
||||
const struct in_addr *pnet_addr,
|
||||
unsigned short port,
|
||||
struct ioc_in_use **ppiiu
|
||||
const struct sockaddr_in *pina,
|
||||
struct ioc_in_use **ppiiu
|
||||
)
|
||||
{
|
||||
int status;
|
||||
@@ -132,9 +147,9 @@ struct ioc_in_use **ppiiu
|
||||
* look for an existing connection
|
||||
*/
|
||||
LOCK;
|
||||
pBHE = lookupBeaconInetAddr(pnet_addr);
|
||||
pBHE = lookupBeaconInetAddr(pina);
|
||||
if(!pBHE){
|
||||
pBHE = createBeaconHashEntry(pnet_addr);
|
||||
pBHE = createBeaconHashEntry(pina, FALSE);
|
||||
if(!pBHE){
|
||||
UNLOCK;
|
||||
return ECA_ALLOCMEM;
|
||||
@@ -142,19 +157,18 @@ struct ioc_in_use **ppiiu
|
||||
}
|
||||
|
||||
if(pBHE->piiu){
|
||||
if(pBHE->piiu->conn_up){
|
||||
if (pBHE->piiu->state!=iiu_disconnected) {
|
||||
*ppiiu = pBHE->piiu;
|
||||
status = ECA_NORMAL;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
status = ECA_DISCONN;
|
||||
}
|
||||
}
|
||||
else{
|
||||
status = create_net_chan(
|
||||
ppiiu,
|
||||
pnet_addr,
|
||||
port,
|
||||
pina,
|
||||
IPPROTO_TCP);
|
||||
if(status == ECA_NORMAL){
|
||||
pBHE->piiu = *ppiiu;
|
||||
@@ -168,23 +182,19 @@ struct ioc_in_use **ppiiu
|
||||
|
||||
|
||||
/*
|
||||
* CREATE_NET_CHANNEL()
|
||||
* CREATE_NET_CHAN()
|
||||
*
|
||||
*/
|
||||
int create_net_chan(
|
||||
struct ioc_in_use **ppiiu,
|
||||
const struct in_addr *pnet_addr, /* only used by TCP connections */
|
||||
unsigned short port,
|
||||
int net_proto
|
||||
struct ioc_in_use **ppiiu,
|
||||
const struct sockaddr_in *pina, /* only used by TCP connections */
|
||||
int net_proto
|
||||
)
|
||||
{
|
||||
struct ioc_in_use *piiu;
|
||||
int status;
|
||||
SOCKET sock;
|
||||
int true = TRUE;
|
||||
#if 0
|
||||
struct sockaddr_in saddr;
|
||||
#endif
|
||||
caAddrNode *pNode;
|
||||
|
||||
LOCK;
|
||||
@@ -207,24 +217,29 @@ int net_proto
|
||||
*/
|
||||
piiu->minor_version_number = CA_UKN_MINOR_VERSION;
|
||||
|
||||
/*
|
||||
* initially there are no claim messages pending
|
||||
*/
|
||||
piiu->claimsPending = FALSE;
|
||||
piiu->recvPending = FALSE;
|
||||
piiu->pushPending = FALSE;
|
||||
|
||||
switch(piiu->sock_proto)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
|
||||
assert(pnet_addr);
|
||||
pNode = (caAddrNode *)calloc(1,sizeof(*pNode));
|
||||
if(!pNode){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
UNLOCK;
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
memset((char *)&pNode->destAddr,0,sizeof(pNode->destAddr));
|
||||
pNode->destAddr.in.sin_family = AF_INET;
|
||||
pNode->destAddr.in.sin_addr = *pnet_addr;
|
||||
pNode->destAddr.in.sin_port = htons (port);
|
||||
|
||||
pNode->destAddr.in = *pina;
|
||||
ellAdd(&piiu->destAddr, &pNode->node);
|
||||
piiu->recvBytes = tcp_recv_msg;
|
||||
piiu->sendBytes = cac_tcp_send_msg_piiu;
|
||||
piiu->sendBytes = cac_connect_iiu;
|
||||
piiu->procInput = ca_process_tcp;
|
||||
piiu->minfreespace = 1;
|
||||
|
||||
@@ -233,6 +248,7 @@ int net_proto
|
||||
SOCK_STREAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == INVALID_SOCKET){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
@@ -251,6 +267,7 @@ int net_proto
|
||||
(char *)&true,
|
||||
sizeof(true));
|
||||
if(status < 0){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
@@ -273,6 +290,7 @@ int net_proto
|
||||
(char *)&true,
|
||||
sizeof true);
|
||||
if(status < 0){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
@@ -299,10 +317,8 @@ int net_proto
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CA_SET_TCP_BUFFER_SIZES
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
|
||||
/* set TCP buffer sizes */
|
||||
i = MAX_MSG_SIZE;
|
||||
@@ -310,9 +326,10 @@ int net_proto
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
&i,
|
||||
(char *)&i,
|
||||
sizeof(i));
|
||||
if(status < 0){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
socket_close(sock);
|
||||
UNLOCK;
|
||||
@@ -323,67 +340,48 @@ int net_proto
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_RCVBUF,
|
||||
&i,
|
||||
(char *)&i,
|
||||
sizeof(i));
|
||||
if(status < 0){
|
||||
free(piiu);
|
||||
socket_close(sock);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
|
||||
/* fetch the TCP send buffer size */
|
||||
i = sizeof(size);
|
||||
status = getsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
(char *)&size,
|
||||
&i);
|
||||
if(status < 0 || i != sizeof(size)){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
socket_close(sock);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* connect */
|
||||
status = connect(
|
||||
sock,
|
||||
&pNode->destAddr.sa,
|
||||
sizeof(pNode->destAddr.sa));
|
||||
if(status < 0){
|
||||
ca_printf("CAC: no conn err=\"%s\"\n", strerror(SOCKERRNO));
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
SEVCHK(ECA_INTERNAL,NULL);
|
||||
}
|
||||
free(piiu);
|
||||
UNLOCK;
|
||||
return ECA_CONN;
|
||||
}
|
||||
|
||||
cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf));
|
||||
cacRingBufferInit(&piiu->recv, sizeof(piiu->recv.buf));
|
||||
cacRingBufferInit(&piiu->send, sizeof(piiu->send.buf));
|
||||
|
||||
cac_gettimeval (&piiu->timeAtLastRecv);
|
||||
|
||||
/*
|
||||
* Save the Host name for efficient access in the
|
||||
* future.
|
||||
*/
|
||||
caHostFromInetAddr(
|
||||
pnet_addr,
|
||||
&pNode->destAddr.in.sin_addr,
|
||||
piiu->host_name_str,
|
||||
sizeof(piiu->host_name_str));
|
||||
|
||||
cac_gettimeval (&piiu->timeAtLastRecv);
|
||||
/*
|
||||
* TCP starts out in the connecting state and later transitions
|
||||
* to the connected state
|
||||
*/
|
||||
piiu->state = iiu_connecting;
|
||||
|
||||
cac_set_iiu_non_blocking (piiu);
|
||||
|
||||
/*
|
||||
* initiate connect sequence
|
||||
*/
|
||||
cac_connect_iiu (piiu);
|
||||
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
|
||||
assert(!pnet_addr);
|
||||
piiu->recvBytes = udp_recv_msg;
|
||||
piiu->sendBytes = cac_udp_send_msg_piiu;
|
||||
piiu->procInput = ca_process_udp;
|
||||
@@ -422,6 +420,30 @@ int net_proto
|
||||
return ECA_CONN;
|
||||
}
|
||||
|
||||
/*
|
||||
* bump up the UDP recv buffer
|
||||
*/
|
||||
{
|
||||
/*
|
||||
*
|
||||
* this allows for faster connects by queuing
|
||||
* additional incomming UDP search response frames
|
||||
*
|
||||
* this allocates a 32k buffer
|
||||
* (uses a power of two)
|
||||
*/
|
||||
int size = 1u<<15u;
|
||||
status = setsockopt(
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_RCVBUF,
|
||||
(char *)&size,
|
||||
sizeof(size));
|
||||
if (status<0) {
|
||||
ca_printf("CAC: setsockopt SO_RCVBUF (err=%s)\n",
|
||||
strerror(SOCKERRNO));
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
memset((char *)&saddr,0,sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
@@ -450,19 +472,28 @@ int net_proto
|
||||
ca_static->ca_server_port);
|
||||
|
||||
|
||||
cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf));
|
||||
cacRingBufferInit(&piiu->recv, sizeof(piiu->recv.buf));
|
||||
cacRingBufferInit(&piiu->send, min(MAX_UDP,
|
||||
sizeof(piiu->send.buf)));
|
||||
|
||||
/*
|
||||
* UDP isnt connection oriented so we tag the piiu
|
||||
* as up immediately
|
||||
*/
|
||||
piiu->state = iiu_connected;
|
||||
|
||||
strncpy(
|
||||
piiu->host_name_str,
|
||||
"<<unknown host>>",
|
||||
sizeof(piiu->host_name_str)-1);
|
||||
|
||||
cac_set_iiu_non_blocking (piiu);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
free(piiu);
|
||||
genLocalExcep (ECA_INTERNAL,"alloc_ioc: ukn protocol");
|
||||
genLocalExcep (ECA_INTERNAL,"create_net_chan: ukn protocol");
|
||||
/*
|
||||
* turn off gcc warnings
|
||||
*/
|
||||
@@ -470,6 +501,33 @@ int net_proto
|
||||
return ECA_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
if (fd_register_func) {
|
||||
LOCKEVENTS;
|
||||
(*fd_register_func)((void *)fd_register_arg, sock, TRUE);
|
||||
UNLOCKEVENTS;
|
||||
}
|
||||
|
||||
/*
|
||||
* add to the list of active IOCs
|
||||
*/
|
||||
ellAdd(&iiuList, &piiu->node);
|
||||
|
||||
*ppiiu = piiu;
|
||||
|
||||
UNLOCK;
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* cac_set_iiu_non_blocking()
|
||||
*/
|
||||
LOCAL void cac_set_iiu_non_blocking (struct ioc_in_use *piiu)
|
||||
{
|
||||
int true = TRUE;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
@@ -480,27 +538,106 @@ int net_proto
|
||||
&true);
|
||||
if(status<0){
|
||||
ca_printf(
|
||||
"Error setting non-blocking io: %s\n",
|
||||
"CAC: failed to set non-blocking because \"%s\"\n",
|
||||
strerror(SOCKERRNO));
|
||||
}
|
||||
}
|
||||
|
||||
if(fd_register_func){
|
||||
LOCKEVENTS;
|
||||
(*fd_register_func)((void *)fd_register_arg, sock, TRUE);
|
||||
UNLOCKEVENTS;
|
||||
/*
|
||||
* cac_connect_iiu()
|
||||
*/
|
||||
LOCAL void cac_connect_iiu (struct ioc_in_use *piiu)
|
||||
{
|
||||
caAddrNode *pNode;
|
||||
int status;
|
||||
|
||||
if (piiu->state==iiu_connected) {
|
||||
ca_printf("CAC: redundant connect() attempt?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (piiu->state==iiu_disconnected) {
|
||||
ca_printf("CAC: connecting when disconnected?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ellCount(&piiu->destAddr)==1u);
|
||||
pNode = (caAddrNode *) ellFirst(&piiu->destAddr);
|
||||
|
||||
/*
|
||||
* attempt to connect to a CA server
|
||||
*/
|
||||
while (1) {
|
||||
int errnoCpy;
|
||||
|
||||
status = connect(
|
||||
piiu->sock_chan,
|
||||
&pNode->destAddr.sa,
|
||||
sizeof(pNode->destAddr.sa));
|
||||
if(status == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
errnoCpy = SOCKERRNO;
|
||||
if (errnoCpy==EISCONN) {
|
||||
/*
|
||||
* called connect after we are already connected
|
||||
* (this appears to be how they provide
|
||||
* connect completion notification)
|
||||
*/
|
||||
break;
|
||||
}
|
||||
else if (
|
||||
errnoCpy==EINPROGRESS ||
|
||||
errnoCpy==EWOULDBLOCK /* for WINSOCK */
|
||||
) {
|
||||
/*
|
||||
* The socket is non-blocking and a
|
||||
* connection attempt has been initiated,
|
||||
* but not completed.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
errnoCpy==EALREADY ||
|
||||
errnoCpy==EINVAL /* for early WINSOCK */
|
||||
) {
|
||||
return;
|
||||
}
|
||||
else if(errnoCpy==EINTR) {
|
||||
/*
|
||||
* restart the system call if interrupted
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
ca_printf(
|
||||
"CAC: Unable to connect port %d on \"%s\" because %d=\"%s\"\n",
|
||||
ntohs(pNode->destAddr.in.sin_port),
|
||||
piiu->host_name_str, errnoCpy,
|
||||
strerror(errnoCpy));
|
||||
TAG_CONN_DOWN(piiu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add to the list of active IOCs
|
||||
* put the iiu into the connected state
|
||||
*/
|
||||
ellAdd(&iiuList, &piiu->node);
|
||||
piiu->state = iiu_connected;
|
||||
|
||||
piiu->conn_up = TRUE;
|
||||
*ppiiu = piiu;
|
||||
piiu->sendBytes = cac_tcp_send_msg_piiu;
|
||||
|
||||
UNLOCK;
|
||||
cac_gettimeval (&piiu->timeAtLastRecv);
|
||||
|
||||
return ECA_NORMAL;
|
||||
/*
|
||||
* When we are done connecting and there are
|
||||
* IOC_CLAIM_CHANNEL requests outstanding
|
||||
* then add them to the outgoing message buffer
|
||||
*/
|
||||
if (piiu->claimsPending) {
|
||||
retryPendingClaims(piiu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -510,7 +647,7 @@ int net_proto
|
||||
void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port)
|
||||
{
|
||||
char *pstr;
|
||||
ENV_PARAM yesno;
|
||||
char yesno[32u];
|
||||
int yes;
|
||||
|
||||
/*
|
||||
@@ -526,8 +663,8 @@ void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port)
|
||||
yes = TRUE;
|
||||
pstr = envGetConfigParam (
|
||||
&EPICS_CA_AUTO_ADDR_LIST,
|
||||
sizeof(yesno.dflt),
|
||||
yesno.dflt);
|
||||
sizeof(yesno),
|
||||
yesno);
|
||||
if (pstr) {
|
||||
if (strstr(pstr,"no")||strstr(pstr,"NO")) {
|
||||
yes = FALSE;
|
||||
@@ -584,7 +721,7 @@ void notify_ca_repeater()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!piiuCast->conn_up) {
|
||||
if (piiuCast->state!=iiu_connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -676,7 +813,7 @@ LOCAL void cac_udp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
/*
|
||||
* check for shutdown in progress
|
||||
*/
|
||||
if(!piiu->conn_up){
|
||||
if(piiu->state!=iiu_connected){
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -733,8 +870,7 @@ LOCAL void cac_udp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
cacRingBufferInit(
|
||||
&piiu->send,
|
||||
min(MAX_UDP, sizeof(piiu->send.buf)));
|
||||
piiu->send_needed = FALSE;
|
||||
|
||||
piiu->pushPending = FALSE;
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
@@ -753,13 +889,12 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
/*
|
||||
* check for shutdown in progress
|
||||
*/
|
||||
if(!piiu->conn_up){
|
||||
if(piiu->state!=iiu_connected){
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
|
||||
|
||||
/*
|
||||
* Check at least twice to see if there is anything
|
||||
* in the ring buffer (in case the block of messages
|
||||
@@ -775,8 +910,17 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
*/
|
||||
if(sendCnt == 0){
|
||||
piiu->sendPending = FALSE;
|
||||
piiu->send_needed = FALSE;
|
||||
piiu->pushPending = FALSE;
|
||||
UNLOCK;
|
||||
|
||||
/*
|
||||
* If we cleared out some send backlog and there are
|
||||
* IOC_CLAIM_CHANNEL requests outstanding
|
||||
* then add them to the outgoing message buffer
|
||||
*/
|
||||
if (piiu->claimsPending) {
|
||||
retryPendingClaims(piiu);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -792,6 +936,7 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
}
|
||||
|
||||
CAC_RING_BUFFER_READ_ADVANCE(&piiu->send, status);
|
||||
|
||||
}
|
||||
|
||||
if (status==0) {
|
||||
@@ -803,7 +948,7 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
localError = SOCKERRNO;
|
||||
|
||||
if( localError == EWOULDBLOCK ||
|
||||
localError == ENOBUFS ||
|
||||
/* localError == ENOBUFS || */
|
||||
localError == EINTR){
|
||||
UNLOCK;
|
||||
return;
|
||||
@@ -822,34 +967,6 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* cac_flush_internal()
|
||||
*
|
||||
* Flush the output - but dont block
|
||||
*
|
||||
*/
|
||||
void cac_flush_internal()
|
||||
{
|
||||
register struct ioc_in_use *piiu;
|
||||
|
||||
LOCK;
|
||||
for( piiu = (IIU *)iiuList.node.next;
|
||||
piiu;
|
||||
piiu = (IIU *)piiu->node.next){
|
||||
|
||||
if(!piiu->conn_up){
|
||||
continue;
|
||||
}
|
||||
if(!piiu->send_needed){
|
||||
continue;
|
||||
}
|
||||
piiu->sendBytes(piiu);
|
||||
}
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cac_clean_iiu_list()
|
||||
@@ -862,7 +979,7 @@ void cac_clean_iiu_list()
|
||||
|
||||
piiu=(IIU *)iiuList.node.next;
|
||||
while(piiu){
|
||||
if(!piiu->conn_up){
|
||||
if (piiu->state==iiu_disconnected) {
|
||||
IIU *pnextiiu;
|
||||
|
||||
pnextiiu = (IIU *)piiu->node.next;
|
||||
@@ -898,7 +1015,7 @@ void ca_process_input_queue()
|
||||
piiu;
|
||||
piiu=(IIU *)piiu->node.next){
|
||||
|
||||
if(!piiu->conn_up){
|
||||
if(piiu->state!=iiu_connected){
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -906,8 +1023,6 @@ void ca_process_input_queue()
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
cac_flush_internal();
|
||||
}
|
||||
|
||||
|
||||
@@ -921,7 +1036,7 @@ LOCAL void tcp_recv_msg(struct ioc_in_use *piiu)
|
||||
unsigned long writeSpace;
|
||||
int status;
|
||||
|
||||
if(!piiu->conn_up){
|
||||
if(piiu->state!=iiu_connected){
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1033,8 +1148,6 @@ LOCAL void ca_process_tcp(struct ioc_in_use *piiu)
|
||||
post_msg_active = FALSE;
|
||||
UNLOCK;
|
||||
|
||||
flow_control(piiu);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1051,7 +1164,7 @@ LOCAL void udp_recv_msg(struct ioc_in_use *piiu)
|
||||
struct udpmsglog *pmsglog;
|
||||
unsigned long bytesAvailable;
|
||||
|
||||
if(!piiu->conn_up){
|
||||
if(piiu->state!=iiu_connected){
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1168,6 +1281,7 @@ LOCAL void ca_process_udp(struct ioc_in_use *piiu)
|
||||
|
||||
/* post message to the user */
|
||||
if(pmsglog->valid){
|
||||
|
||||
status = post_msg(
|
||||
piiu,
|
||||
&pmsglog->addr.sin_addr,
|
||||
@@ -1251,7 +1365,7 @@ LOCAL void close_ioc (IIU *piiu)
|
||||
*/
|
||||
pNode = (caAddrNode *) piiu->destAddr.node.next;
|
||||
assert (pNode);
|
||||
removeBeaconInetAddr (&pNode->destAddr.in.sin_addr);
|
||||
removeBeaconInetAddr (&pNode->destAddr.in);
|
||||
|
||||
/*
|
||||
* Mark all of their channels disconnected
|
||||
@@ -1311,19 +1425,13 @@ LOCAL void close_ioc (IIU *piiu)
|
||||
*/
|
||||
void cacDisconnectChannel(ciu chix, enum channel_state state)
|
||||
{
|
||||
struct ioc_in_use *piiu;
|
||||
|
||||
chix->type = TYPENOTCONN;
|
||||
chix->count = 0U;
|
||||
chix->id.sid = ~0U;
|
||||
chix->count = 0u;
|
||||
chix->id.sid = ~0u;
|
||||
chix->ar.read_access = FALSE;
|
||||
chix->ar.write_access = FALSE;
|
||||
|
||||
/*
|
||||
* try to reconnect
|
||||
*/
|
||||
chix->retry = 0U;
|
||||
|
||||
/*
|
||||
* call their connection handler as required
|
||||
*/
|
||||
@@ -1359,16 +1467,13 @@ void cacDisconnectChannel(ciu chix, enum channel_state state)
|
||||
}
|
||||
UNLOCKEVENTS;
|
||||
}
|
||||
piiu = (struct ioc_in_use *)chix->piiu;
|
||||
ellDelete(&piiu->chidlist, &chix->node);
|
||||
assert (piiuCast);
|
||||
chix->piiu = piiuCast;
|
||||
ellAdd(&piiuCast->chidlist, &chix->node);
|
||||
|
||||
removeFromChanList(chix);
|
||||
/*
|
||||
* Try to reconnect this channel
|
||||
* try to reconnect
|
||||
*/
|
||||
ca_static->ca_search_retry = 0;
|
||||
assert (piiuCast);
|
||||
addToChanList(chix, piiuCast);
|
||||
cacSetRetryInterval(0u);
|
||||
}
|
||||
|
||||
|
||||
@@ -1468,11 +1573,11 @@ unsigned long nBytes)
|
||||
unsigned long actualBytes;
|
||||
char *pCharBuf;
|
||||
|
||||
actualBytes = 0;
|
||||
actualBytes = 0u;
|
||||
pCharBuf = pBuf;
|
||||
while(TRUE){
|
||||
potentialBytes = cacRingBufferReadSize(pRing, TRUE);
|
||||
if(potentialBytes == 0){
|
||||
if(potentialBytes == 0u){
|
||||
return actualBytes;
|
||||
}
|
||||
potentialBytes = min(potentialBytes, nBytes-actualBytes);
|
||||
@@ -1502,11 +1607,11 @@ unsigned long nBytes)
|
||||
unsigned long actualBytes;
|
||||
const char *pCharBuf;
|
||||
|
||||
actualBytes = 0;
|
||||
actualBytes = 0u;
|
||||
pCharBuf = pBuf;
|
||||
while(TRUE){
|
||||
potentialBytes = cacRingBufferWriteSize(pRing, TRUE);
|
||||
if(potentialBytes == 0){
|
||||
if(potentialBytes == 0u){
|
||||
return actualBytes;
|
||||
}
|
||||
potentialBytes = min(potentialBytes, nBytes-actualBytes);
|
||||
@@ -1530,8 +1635,8 @@ LOCAL void cacRingBufferInit(struct ca_buffer *pBuf, unsigned long size)
|
||||
{
|
||||
assert(size<=sizeof(pBuf->buf));
|
||||
pBuf->max_msg = size;
|
||||
pBuf->rdix = 0;
|
||||
pBuf->wtix = 0;
|
||||
pBuf->rdix = 0u;
|
||||
pBuf->wtix = 0u;
|
||||
pBuf->readLast = TRUE;
|
||||
}
|
||||
|
||||
@@ -1556,7 +1661,7 @@ unsigned long cacRingBufferReadSize(struct ca_buffer *pBuf, int contiguous)
|
||||
count = pBuf->wtix - pBuf->rdix;
|
||||
}
|
||||
else if(pBuf->readLast){
|
||||
count = 0;
|
||||
count = 0u;
|
||||
}
|
||||
else{
|
||||
if(contiguous){
|
||||
@@ -1603,7 +1708,7 @@ unsigned long cacRingBufferWriteSize(struct ca_buffer *pBuf, int contiguous)
|
||||
}
|
||||
}
|
||||
else{
|
||||
count = 0;
|
||||
count = 0u;
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -1653,21 +1758,18 @@ char *localHostName()
|
||||
/*
|
||||
* caAddConfiguredAddr()
|
||||
*/
|
||||
void caAddConfiguredAddr(ELLLIST *pList, ENV_PARAM *pEnv,
|
||||
void caAddConfiguredAddr(ELLLIST *pList, const ENV_PARAM *pEnv,
|
||||
SOCKET socket, int port)
|
||||
{
|
||||
caAddrNode *pNode;
|
||||
ENV_PARAM list;
|
||||
char *pStr;
|
||||
char *pToken;
|
||||
const char *pStr;
|
||||
const char *pToken;
|
||||
caAddr addr;
|
||||
caAddr localAddr;
|
||||
char buf[32u]; /* large enough to hold an IP address */
|
||||
int status;
|
||||
|
||||
pStr = envGetConfigParam(
|
||||
pEnv,
|
||||
sizeof(list.dflt),
|
||||
list.dflt);
|
||||
pStr = envGetConfigParamPtr(pEnv);
|
||||
if(!pStr){
|
||||
return;
|
||||
}
|
||||
@@ -1680,7 +1782,7 @@ void caAddConfiguredAddr(ELLLIST *pList, ENV_PARAM *pEnv,
|
||||
return;
|
||||
}
|
||||
|
||||
while( (pToken = getToken(&pStr)) ){
|
||||
while( (pToken = getToken(&pStr, buf, sizeof(buf))) ){
|
||||
memset((char *)&addr,0,sizeof(addr));
|
||||
addr.in.sin_family = AF_INET;
|
||||
addr.in.sin_port = htons(port);
|
||||
@@ -1712,32 +1814,28 @@ void caAddConfiguredAddr(ELLLIST *pList, ENV_PARAM *pEnv,
|
||||
/*
|
||||
* getToken()
|
||||
*/
|
||||
LOCAL char *getToken(char **ppString)
|
||||
LOCAL char *getToken(const char **ppString, char *pBuf, unsigned bufSIze)
|
||||
{
|
||||
char *pToken;
|
||||
char *pStr;
|
||||
const char *pToken;
|
||||
unsigned i;
|
||||
|
||||
pToken = *ppString;
|
||||
while(isspace(*pToken)&&*pToken){
|
||||
pToken++;
|
||||
}
|
||||
|
||||
pStr = pToken;
|
||||
while(!isspace(*pStr)&&*pStr){
|
||||
pStr++;
|
||||
for (i=0u; i<bufSIze; i++) {
|
||||
if (isspace(pToken[i]) || pToken[i]=='\0') {
|
||||
pBuf[i] = '\0';
|
||||
break;
|
||||
}
|
||||
pBuf[i] = pToken[i];
|
||||
}
|
||||
|
||||
if(isspace(*pStr)){
|
||||
*pStr = '\0';
|
||||
*ppString = pStr+1;
|
||||
}
|
||||
else{
|
||||
*ppString = pStr;
|
||||
assert(*pStr == '\0');
|
||||
}
|
||||
*ppString = &pToken[i];
|
||||
|
||||
if(*pToken){
|
||||
return pToken;
|
||||
return pBuf;
|
||||
}
|
||||
else{
|
||||
return NULL;
|
||||
@@ -1770,7 +1868,7 @@ void caPrintAddrList(ELLLIST *pList)
|
||||
/*
|
||||
* caFetchPortConfig()
|
||||
*/
|
||||
unsigned short caFetchPortConfig(ENV_PARAM *pEnv, unsigned short defaultPort)
|
||||
unsigned short caFetchPortConfig(const ENV_PARAM *pEnv, unsigned short defaultPort)
|
||||
{
|
||||
long longStatus;
|
||||
long epicsParam;
|
||||
@@ -1819,8 +1917,31 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
/*
|
||||
* manage search timers and detect disconnects
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
manage_conn();
|
||||
|
||||
/*
|
||||
* first check for pending recv's with a zero time out so that
|
||||
* 1) flow control works correctly (and)
|
||||
* 2) we queue up sends resulting from recvs properly
|
||||
* (this results in improved max throughput)
|
||||
*/
|
||||
while (TRUE) {
|
||||
LD_CA_TIME (0.0, &timeout);
|
||||
/*
|
||||
* NOTE cac_select_io() will set the
|
||||
* send flag for a particular iiu irregradless
|
||||
* of what is requested here if piiu->pushPending
|
||||
* is set
|
||||
*/
|
||||
count = cac_select_io(&timeout, CA_DO_RECVS);
|
||||
if (count<=0) {
|
||||
break;
|
||||
}
|
||||
ca_process_input_queue();
|
||||
}
|
||||
/*
|
||||
* next check for pending writes's with the specified time out
|
||||
*/
|
||||
timeout = *ptimeout;
|
||||
while (TRUE) {
|
||||
count = cac_select_io(&timeout, CA_DO_RECVS|CA_DO_SENDS);
|
||||
@@ -1842,8 +1963,7 @@ void cac_mux_io(struct timeval *ptimeout)
|
||||
LD_CA_TIME (SELECT_POLL, &timeout);
|
||||
}
|
||||
else {
|
||||
ca_static->ca_flush_pending
|
||||
= FALSE;
|
||||
ca_static->ca_flush_pending = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1874,14 +1994,16 @@ int caSendMsgPending()
|
||||
piiu;
|
||||
piiu = (IIU *) ellNext(&piiu->node)){
|
||||
|
||||
if(piiu == piiuCast || piiu->conn_up == FALSE){
|
||||
if(piiu == piiuCast){
|
||||
continue;
|
||||
}
|
||||
|
||||
bytesPending = cacRingBufferReadSize(&piiu->send, FALSE);
|
||||
if(bytesPending > 0U){
|
||||
pending = TRUE;
|
||||
}
|
||||
if (piiu->state == iiu_connected) {
|
||||
bytesPending = cacRingBufferReadSize(&piiu->send, FALSE);
|
||||
if(bytesPending > 0u){
|
||||
pending = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
|
||||
|
||||
160
src/ca/iocinf.h
160
src/ca/iocinf.h
@@ -32,6 +32,21 @@
|
||||
/************************************************************************/
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.63 1997/05/05 04:45:25 jhill
|
||||
* send_needed => pushPending, and added ca_number_iiu_in_fc
|
||||
*
|
||||
* Revision 1.62 1997/04/29 06:11:08 jhill
|
||||
* use free lists
|
||||
*
|
||||
* Revision 1.61 1997/04/23 17:05:07 jhill
|
||||
* pc port changes
|
||||
*
|
||||
* Revision 1.60 1997/04/10 19:26:24 jhill
|
||||
* asynch connect, faster connect, ...
|
||||
*
|
||||
* Revision 1.59 1997/01/22 21:10:26 jhill
|
||||
* smaller external sym name for VAXC
|
||||
*
|
||||
* Revision 1.58 1996/11/02 00:50:56 jhill
|
||||
* many pc port, const in API, and other changes
|
||||
*
|
||||
@@ -127,8 +142,6 @@ HDRVERSIONID(iocinfh, "$Id$")
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
/*
|
||||
* OS dependent includes
|
||||
*/
|
||||
@@ -138,13 +151,26 @@ HDRVERSIONID(iocinfh, "$Id$")
|
||||
/*
|
||||
* EPICS includes
|
||||
*/
|
||||
#if defined(epicsExportSharedSymbols)
|
||||
#error suspect that libCom was not imported
|
||||
#endif
|
||||
|
||||
#include "epicsAssert.h"
|
||||
#include "cadef.h"
|
||||
#include "bucketLib.h"
|
||||
#include "ellLib.h"
|
||||
#include "envDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
|
||||
#if defined(epicsExportSharedSymbols)
|
||||
#error suspect that libCom was not imported
|
||||
#endif
|
||||
|
||||
/*
|
||||
* this is defined only after we import from libCom above
|
||||
*/
|
||||
#define epicsExportSharedSymbols
|
||||
#include "cadef.h"
|
||||
|
||||
/*
|
||||
* CA private includes
|
||||
*/
|
||||
@@ -215,8 +241,8 @@ if(!ca_static){ \
|
||||
/* throw out requests prior to last ECA_TIMEOUT from ca_pend */
|
||||
#define VALID_MSG(PIIU) (piiu->read_seq == piiu->cur_read_seq)
|
||||
|
||||
#define SETPENDRECV {pndrecvcnt++;}
|
||||
#define CLRPENDRECV {if(--pndrecvcnt<1){POST_IO_EV;}}
|
||||
#define SETPENDRECV {pndrecvcnt++;}
|
||||
#define CLRPENDRECV {if(--pndrecvcnt<1u){POST_IO_EV;}}
|
||||
|
||||
struct udpmsglog{
|
||||
long nbytes;
|
||||
@@ -242,15 +268,6 @@ typedef struct timeval ca_time;
|
||||
((PCATIME)->tv_sec = (long) (FLOAT_TIME), \
|
||||
(PCATIME)->tv_usec = (long) ( ((FLOAT_TIME)-(PCATIME)->tv_sec)*USEC_PER_SEC ))
|
||||
|
||||
/*
|
||||
* dont adjust
|
||||
*/
|
||||
#ifdef CA_GLBLSOURCE
|
||||
const ca_time CA_CURRENT_TIME = {0,0};
|
||||
#else /*CA_GLBLSOURCE*/
|
||||
extern const ca_time CA_CURRENT_TIME;
|
||||
#endif /*CA_GLBLSOURCE*/
|
||||
|
||||
/*
|
||||
* these control the duration and period of name resolution
|
||||
* broadcasts
|
||||
@@ -259,6 +276,11 @@ extern const ca_time CA_CURRENT_TIME;
|
||||
*/
|
||||
#define MAXCONNTRIES 30 /* N conn retries on unchanged net */
|
||||
|
||||
/*
|
||||
* A prime number works best here (see comment in retrySearchRequest()
|
||||
*/
|
||||
#define TRIESPERFRAME 5u /* N UDP frames per search try */
|
||||
|
||||
/*
|
||||
* NOTE: These must be larger than one vxWorks tick or we will end up
|
||||
* using the CPU. A vxWorks tick is usually 1/60th of a sec.
|
||||
@@ -296,12 +318,21 @@ typedef struct caclient_put_notify{
|
||||
unsigned long valueSize; /* size of block pointed to by dbPutNotify */
|
||||
void (*caUserCallback)(struct event_handler_args);
|
||||
void *caUserArg;
|
||||
struct ca_static *pcas;
|
||||
struct CA_STATIC *pcas;
|
||||
int busy;
|
||||
}CACLIENTPUTNOTIFY;
|
||||
#endif /*vxWorks*/
|
||||
|
||||
#define MAX_CONTIGUOUS_MSG_COUNT 2
|
||||
/*
|
||||
* this determines the number of messages received
|
||||
* without a delay in between before we go into
|
||||
* monitor flow control
|
||||
*
|
||||
* turning this down effect maximum throughput
|
||||
* because we dont get an optimal number of bytes
|
||||
* per network frame
|
||||
*/
|
||||
#define MAX_CONTIGUOUS_MSG_COUNT 10
|
||||
|
||||
/*
|
||||
* ! lock needs to be applied when an id is allocated !
|
||||
@@ -318,13 +349,8 @@ typedef struct caclient_put_notify{
|
||||
#define iiuList (ca_static->ca_iiuList)
|
||||
#define piiuCast (ca_static->ca_piiuCast)
|
||||
#define pndrecvcnt (ca_static->ca_pndrecvcnt)
|
||||
#define chidlist_pend (ca_static->ca_chidlist_pend)
|
||||
#define chidlist_conn (ca_static->ca_chidlist_conn)
|
||||
#define chidlist_noreply\
|
||||
(ca_static->ca_chidlist_noreply)
|
||||
#define ioeventlist (ca_static->ca_ioeventlist)
|
||||
#define nxtiiu (ca_static->ca_nxtiiu)
|
||||
#define free_event_list (ca_static->ca_free_event_list)
|
||||
#define pend_read_list (ca_static->ca_pend_read_list)
|
||||
#define pend_write_list (ca_static->ca_pend_write_list)
|
||||
#define fd_register_func\
|
||||
@@ -343,7 +369,6 @@ typedef struct caclient_put_notify{
|
||||
# define client_lock (ca_static->ca_client_lock)
|
||||
# define event_lock (ca_static->ca_event_lock)
|
||||
# define local_chidlist (ca_static->ca_local_chidlist)
|
||||
# define dbfree_ev_list (ca_static->ca_dbfree_ev_list)
|
||||
# define lcl_buff_list (ca_static->ca_lcl_buff_list)
|
||||
# define event_tid (ca_static->ca_event_tid)
|
||||
#endif
|
||||
@@ -392,9 +417,11 @@ struct ca_buffer{
|
||||
#define TAG_CONN_DOWN(PIIU) \
|
||||
( \
|
||||
/* ca_printf("Tagging connection down at %d in %s\n", __LINE__, __FILE__), */ \
|
||||
(PIIU)->conn_up = FALSE \
|
||||
(PIIU)->state = iiu_disconnected\
|
||||
)
|
||||
|
||||
enum iiu_conn_state{iiu_connecting, iiu_connected, iiu_disconnected};
|
||||
|
||||
/*
|
||||
* One per IOC
|
||||
*/
|
||||
@@ -410,7 +437,7 @@ typedef struct ioc_in_use{
|
||||
struct ca_buffer send;
|
||||
struct ca_buffer recv;
|
||||
caHdr curMsg;
|
||||
struct ca_static *pcas;
|
||||
struct CA_STATIC *pcas;
|
||||
void *pCurData;
|
||||
void (*sendBytes)(struct ioc_in_use *);
|
||||
void (*recvBytes)(struct ioc_in_use *);
|
||||
@@ -424,25 +451,27 @@ typedef struct ioc_in_use{
|
||||
unsigned cur_read_seq;
|
||||
unsigned minfreespace;
|
||||
char host_name_str[32];
|
||||
unsigned char state; /* for use with iiu_conn_state enum */
|
||||
|
||||
/*
|
||||
* bit fields placed together for better packing density
|
||||
*/
|
||||
unsigned client_busy:1;
|
||||
unsigned echoPending:1;
|
||||
unsigned send_needed:1; /* CA needs a send */
|
||||
unsigned conn_up:1; /* boolean: T-conn /F-disconn */
|
||||
unsigned sendPending:1;
|
||||
unsigned claimsPending:1;
|
||||
unsigned recvPending:1;
|
||||
unsigned pushPending:1;
|
||||
}IIU;
|
||||
|
||||
/*
|
||||
* for the beacon's recvd hash table
|
||||
*/
|
||||
#define BHT_INET_ADDR_MASK 0x7f
|
||||
#define BHT_INET_ADDR_MASK 0xff
|
||||
typedef struct beaconHashEntry{
|
||||
struct beaconHashEntry *pNext;
|
||||
IIU *piiu;
|
||||
struct in_addr inetAddr;
|
||||
struct sockaddr_in inetAddr;
|
||||
ca_time timeStamp;
|
||||
ca_real averagePeriod;
|
||||
}bhe;
|
||||
@@ -457,16 +486,13 @@ typedef struct {
|
||||
fd_set writeMask;
|
||||
}caFDInfo;
|
||||
|
||||
struct ca_static{
|
||||
struct CA_STATIC {
|
||||
ELLLIST ca_iiuList;
|
||||
ELLLIST ca_ioeventlist;
|
||||
ELLLIST ca_free_event_list;
|
||||
ELLLIST ca_pend_read_list;
|
||||
ELLLIST ca_pend_write_list;
|
||||
ELLLIST activeCASG;
|
||||
ELLLIST freeCASG;
|
||||
ELLLIST activeCASGOP;
|
||||
ELLLIST freeCASGOP;
|
||||
ELLLIST putCvrtBuf;
|
||||
ELLLIST fdInfoFreeList;
|
||||
ELLLIST fdInfoList;
|
||||
@@ -475,9 +501,7 @@ struct ca_static{
|
||||
ca_time ca_conn_retry_delay;
|
||||
ca_time ca_last_repeater_try;
|
||||
ca_real ca_connectTMO;
|
||||
long ca_pndrecvcnt;
|
||||
unsigned long ca_nextSlowBucketId;
|
||||
unsigned long ca_nextFastBucketId;
|
||||
ca_time programBeginTime;
|
||||
IIU *ca_piiuCast;
|
||||
void (*ca_exception_func)
|
||||
(struct exception_handler_args);
|
||||
@@ -491,11 +515,24 @@ struct ca_static{
|
||||
BUCKET *ca_pSlowBucket;
|
||||
BUCKET *ca_pFastBucket;
|
||||
bhe *ca_beaconHash[BHT_INET_ADDR_MASK+1];
|
||||
unsigned ca_repeater_tries;
|
||||
void *ca_ioBlockFreeListPVT;
|
||||
void *ca_sgFreeListPVT;
|
||||
void *ca_sgopFreeListPVT;
|
||||
ciu ca_pEndOfBCastList;
|
||||
unsigned ca_search_responses; /* num valid search resp within seq # */
|
||||
unsigned ca_search_tries; /* num search tries within seq # */
|
||||
unsigned ca_search_retry; /* search retry seq number */
|
||||
unsigned ca_search_responses; /* num search resp within seq # */
|
||||
unsigned ca_min_retry; /* min retry no so far */
|
||||
unsigned ca_frames_per_try; /* # of UDP frames per search try */
|
||||
unsigned ca_pndrecvcnt;
|
||||
unsigned ca_nextSlowBucketId;
|
||||
unsigned ca_nextFastBucketId;
|
||||
unsigned ca_repeater_tries;
|
||||
unsigned ca_number_iiu_in_fc;
|
||||
unsigned short ca_server_port;
|
||||
unsigned short ca_repeater_port;
|
||||
unsigned short ca_search_retry_seq_no; /* search retry seq number */
|
||||
unsigned short ca_seq_no_at_list_begin; /* search retry seq number at beg of list*/
|
||||
char ca_sprintf_buf[256];
|
||||
char ca_new_err_code_msg_buf[128u];
|
||||
unsigned ca_post_msg_active:1;
|
||||
@@ -509,11 +546,11 @@ struct ca_static{
|
||||
SEM_ID ca_event_lock; /* dont allow events to preempt */
|
||||
SEM_ID ca_putNotifyLock;
|
||||
ELLLIST ca_local_chidlist;
|
||||
ELLLIST ca_dbfree_ev_list;
|
||||
ELLLIST ca_lcl_buff_list;
|
||||
ELLLIST ca_putNotifyQue;
|
||||
ELLLIST ca_taskVarList;
|
||||
void *ca_evuser;
|
||||
void *ca_dbMonixFreeList;
|
||||
int ca_event_tid;
|
||||
int ca_tid;
|
||||
int recv_tid;
|
||||
@@ -560,7 +597,7 @@ typedef struct{
|
||||
*/
|
||||
|
||||
GLBLTYPE
|
||||
struct ca_static *ca_static;
|
||||
struct CA_STATIC *ca_static;
|
||||
|
||||
/*
|
||||
* CA internal functions
|
||||
@@ -572,23 +609,24 @@ void cac_mux_io(struct timeval *ptimeout);
|
||||
int repeater_installed(void);
|
||||
int search_msg(ciu chix, int reply_type);
|
||||
int ca_request_event(evid monix);
|
||||
void ca_busy_message(struct ioc_in_use *piiu);
|
||||
void ca_ready_message(struct ioc_in_use *piiu);
|
||||
int ca_busy_message(struct ioc_in_use *piiu);
|
||||
int ca_ready_message(struct ioc_in_use *piiu);
|
||||
void noop_msg(struct ioc_in_use *piiu);
|
||||
int echo_request(struct ioc_in_use *piiu, ca_time *pCurrentTime);
|
||||
void issue_claim_channel(struct ioc_in_use *piiu, chid pchan);
|
||||
int issue_claim_channel(chid pchan);
|
||||
void issue_identify_client(struct ioc_in_use *piiu);
|
||||
void issue_client_host_name(struct ioc_in_use *piiu);
|
||||
int ca_defunct(void);
|
||||
int ca_printf(char *pformat, ...);
|
||||
void manage_conn(int silent);
|
||||
void mark_server_available(const struct in_addr *pnet_addr);
|
||||
void flow_control(struct ioc_in_use *piiu);
|
||||
void manage_conn();
|
||||
void mark_server_available(const struct sockaddr_in *pnet_addr);
|
||||
void flow_control_on(struct ioc_in_use *piiu);
|
||||
void flow_control_off(struct ioc_in_use *piiu);
|
||||
int broadcast_addr(struct in_addr *pcastaddr);
|
||||
void ca_repeater(void);
|
||||
void cac_recv_task(int tid);
|
||||
void ca_sg_init(void);
|
||||
void ca_sg_shutdown(struct ca_static *ca_temp);
|
||||
void ca_sg_shutdown(struct CA_STATIC *ca_temp);
|
||||
int cac_select_io(struct timeval *ptimeout, int flags);
|
||||
void caHostFromInetAddr(
|
||||
const struct in_addr *pnet_addr,
|
||||
@@ -602,9 +640,8 @@ int post_msg(
|
||||
unsigned long blockSize
|
||||
);
|
||||
int alloc_ioc(
|
||||
const struct in_addr *pnet_addr,
|
||||
unsigned short port,
|
||||
struct ioc_in_use **ppiiu
|
||||
const struct sockaddr_in *pina,
|
||||
struct ioc_in_use **ppiiu
|
||||
);
|
||||
unsigned long cacRingBufferWrite(
|
||||
struct ca_buffer *pRing,
|
||||
@@ -635,32 +672,30 @@ char *localUserName(void);
|
||||
char *localHostName(void);
|
||||
|
||||
int create_net_chan(
|
||||
struct ioc_in_use **ppiiu,
|
||||
const struct in_addr *pnet_addr, /* only used by TCP connections */
|
||||
unsigned short port,
|
||||
int net_proto
|
||||
struct ioc_in_use **ppiiu,
|
||||
const struct sockaddr_in *pina, /* only used by TCP connections */
|
||||
int net_proto
|
||||
);
|
||||
|
||||
void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port);
|
||||
|
||||
int ca_os_independent_init (void);
|
||||
|
||||
void freeBeaconHash(struct ca_static *ca_temp);
|
||||
void removeBeaconInetAddr(const struct in_addr *pnet_addr);
|
||||
bhe *lookupBeaconInetAddr(const struct in_addr *pnet_addr);
|
||||
bhe *createBeaconHashEntry(const struct in_addr *pnet_addr);
|
||||
void freeBeaconHash(struct CA_STATIC *ca_temp);
|
||||
void removeBeaconInetAddr(const struct sockaddr_in *pnet_addr);
|
||||
bhe *lookupBeaconInetAddr(const struct sockaddr_in *pnet_addr);
|
||||
bhe *createBeaconHashEntry(const struct sockaddr_in *pnet_addr, unsigned sawBeacon);
|
||||
void notify_ca_repeater(void);
|
||||
void cac_clean_iiu_list(void);
|
||||
|
||||
void ca_process_input_queue(void);
|
||||
void cac_flush_internal(void);
|
||||
void cac_block_for_io_completion(struct timeval *pTV);
|
||||
void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV);
|
||||
void os_specific_sg_create(CASG *pcasg);
|
||||
void os_specific_sg_delete(CASG *pcasg);
|
||||
void os_specific_sg_io_complete(CASG *pcasg);
|
||||
int cac_os_depen_init(struct ca_static *pcas);
|
||||
void cac_os_depen_exit (struct ca_static *pcas);
|
||||
int cac_os_depen_init(struct CA_STATIC *pcas);
|
||||
void cac_os_depen_exit (struct CA_STATIC *pcas);
|
||||
void ca_process_exit();
|
||||
void ca_spawn_repeater(void);
|
||||
void cac_gettimeval(struct timeval *pt);
|
||||
@@ -677,6 +712,11 @@ void genLocalExcepWFL(long stat, char *ctx,
|
||||
char *pFile, unsigned line);
|
||||
#define genLocalExcep(STAT, PCTX) \
|
||||
genLocalExcepWFL (STAT, PCTX, __FILE__, __LINE__)
|
||||
void cac_reconnect_channel(ciu chan);
|
||||
void retryPendingClaims(IIU *piiu);
|
||||
void cacSetRetryInterval(unsigned retryNo);
|
||||
void addToChanList(ciu chan, IIU *piiu);
|
||||
void removeFromChanList(ciu chan);
|
||||
|
||||
/*
|
||||
* !!KLUDGE!!
|
||||
|
||||
@@ -27,7 +27,12 @@
|
||||
#ifndef _NET_CONVERT_H
|
||||
#define _NET_CONVERT_H
|
||||
|
||||
#include <db_access.h>
|
||||
#include "db_access.h"
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Here are the definitions for architecture dependent byte ordering
|
||||
@@ -85,7 +90,7 @@ typedef void CACVRTFUNC(void *pSrc, void *pDest, int hton, unsigned long count);
|
||||
|
||||
#ifdef CONVERSION_REQUIRED
|
||||
/* cvrt is (array of) (pointer to) (function returning) int */
|
||||
extern CACVRTFUNC *cac_dbr_cvrt[];
|
||||
epicsShareExtern CACVRTFUNC *cac_dbr_cvrt[LAST_BUFFER_TYPE+1];
|
||||
#endif
|
||||
|
||||
|
||||
@@ -100,11 +105,15 @@ extern CACVRTFUNC *cac_dbr_cvrt[];
|
||||
#ifdef CA_LITTLE_ENDIAN
|
||||
# ifndef ntohs
|
||||
# define ntohs(SHORT)\
|
||||
( ((SHORT) & 0x00ff) << 8 | ((SHORT) & 0xff00) >> 8 )
|
||||
( (dbr_short_t)\
|
||||
(((SHORT) & (dbr_short_t) 0x00ff) << 8 |\
|
||||
((SHORT) & (dbr_short_t) 0xff00) >> 8) )
|
||||
# endif
|
||||
# ifndef htons
|
||||
# define htons(SHORT)\
|
||||
( ((SHORT) & 0x00ff) << 8 | ((SHORT) & 0xff00) >> 8 )
|
||||
( (dbr_short_t)\
|
||||
(((SHORT) & (dbr_short_t) 0x00ff) << 8 |\
|
||||
((SHORT) & (dbr_short_t) 0xff00) >> 8) )
|
||||
# endif
|
||||
#else
|
||||
# ifndef ntohs
|
||||
@@ -119,20 +128,20 @@ extern CACVRTFUNC *cac_dbr_cvrt[];
|
||||
#ifdef CA_LITTLE_ENDIAN
|
||||
# ifndef ntohl
|
||||
# define ntohl(LONG)\
|
||||
(\
|
||||
((LONG) & 0xff000000) >> 24 |\
|
||||
((LONG) & 0x000000ff) << 24 |\
|
||||
((LONG) & 0x0000ff00) << 8 |\
|
||||
((LONG) & 0x00ff0000) >> 8\
|
||||
( (dbr_long_t) (\
|
||||
( ((dbr_ulong_t)LONG) & 0xff000000 ) >> 24u |\
|
||||
( ((dbr_ulong_t)LONG) & 0x000000ff ) << 24u |\
|
||||
( ((dbr_ulong_t)LONG) & 0x0000ff00 ) << 8u |\
|
||||
( ((dbr_ulong_t)LONG) & 0x00ff0000 ) >> 8u )\
|
||||
)
|
||||
# endif
|
||||
# ifndef htonl
|
||||
# define htonl(LONG)\
|
||||
(\
|
||||
((LONG) & 0x000000ff) << 24 |\
|
||||
((LONG) & 0xff000000) >> 24 |\
|
||||
((LONG) & 0x00ff0000) >> 8 |\
|
||||
((LONG) & 0x0000ff00) << 8\
|
||||
( (dbr_long_t) (\
|
||||
( ((dbr_ulong_t)(LONG)) & 0x000000ff ) << 24u |\
|
||||
( ((dbr_ulong_t)(LONG)) & 0xff000000 ) >> 24u |\
|
||||
( ((dbr_ulong_t)(LONG)) & 0x00ff0000 ) >> 8u |\
|
||||
( ((dbr_ulong_t)(LONG)) & 0x0000ff00 ) << 8u )\
|
||||
)
|
||||
# endif
|
||||
# else
|
||||
@@ -179,4 +188,8 @@ extern CACVRTFUNC *cac_dbr_cvrt[];
|
||||
void dbr_ntohf(dbr_float_t *pNet, dbr_float_t *pHost);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* define _NET_CONVERT_H */
|
||||
|
||||
@@ -39,7 +39,7 @@ static char *sccsId = "@(#) $Id$";
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock.h>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
@@ -48,7 +48,7 @@ static char *sccsId = "@(#) $Id$";
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include "epicsAssert.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -56,8 +56,8 @@ static char *os_depenhSccsId = "$Id$";
|
||||
# include <taskLib.h>
|
||||
# include <vxLib.h>
|
||||
|
||||
# include <task_params.h>
|
||||
# include <taskwd.h>
|
||||
# include "task_params.h"
|
||||
# include "taskwd.h"
|
||||
|
||||
# define CA_OS_CONFIGURED
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* Revision 1.21 1997/04/10 19:26:17 jhill
|
||||
* asynch connect, faster connect, ...
|
||||
*
|
||||
* Revision 1.20 1996/11/02 00:51:02 jhill
|
||||
* many pc port, const in API, and other changes
|
||||
*
|
||||
* Revision 1.19 1996/07/09 22:41:02 jhill
|
||||
* pass nill 2nd arg to gettimeofday()
|
||||
*
|
||||
@@ -52,9 +58,6 @@
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
#define _POSIX_C_SOURCE 3 /* for solaris and "cc -Xc" */
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
/*
|
||||
* cac_gettimeval
|
||||
@@ -110,7 +113,7 @@ void os_specific_sg_delete(CASG *pcasg)
|
||||
/*
|
||||
* CAC_ADD_TASK_VARIABLE()
|
||||
*/
|
||||
int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
int cac_add_task_variable(struct CA_STATIC *ca_temp)
|
||||
{
|
||||
ca_static = ca_temp;
|
||||
return ECA_NORMAL;
|
||||
@@ -120,40 +123,12 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
/*
|
||||
* cac_os_depen_init()
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
int cac_os_depen_init(struct CA_STATIC *pcas)
|
||||
{
|
||||
int status;
|
||||
struct sigaction sa;
|
||||
|
||||
ca_static = pcas;
|
||||
|
||||
/*
|
||||
* dont allow disconnect to terminate process
|
||||
* when running in UNIX environment
|
||||
*
|
||||
* allow error to be returned to sendto()
|
||||
* instead of handling disconnect at interrupt
|
||||
*/
|
||||
status = sigaction(SIGPIPE, NULL, &sa);
|
||||
if (status==0) {
|
||||
if (sa.sa_handler == SIG_DFL) {
|
||||
sa.sa_handler = SIG_IGN;
|
||||
status = sigaction(SIGPIPE, &sa, NULL);
|
||||
if (status) {
|
||||
ca_printf(
|
||||
"%s: Error from signal replace was \"%s\"\n",
|
||||
__FILE__,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ca_printf(
|
||||
"%s: Error from signal query was \"%s\"\n",
|
||||
__FILE__,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
status = ca_os_independent_init ();
|
||||
|
||||
return status;
|
||||
@@ -163,7 +138,7 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
/*
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
void cac_os_depen_exit (struct CA_STATIC *pcas)
|
||||
{
|
||||
ca_static = pcas;
|
||||
ca_process_exit();
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
* datagram socket (and watching for ECONNREFUSED)
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.38 1996/11/02 00:51:04 jhill
|
||||
* many pc port, const in API, and other changes
|
||||
*
|
||||
* Revision 1.37 1996/09/04 20:02:32 jhill
|
||||
* fixed gcc warning
|
||||
*
|
||||
@@ -298,7 +301,8 @@ LOCAL void verifyClients()
|
||||
else {
|
||||
if (SOCKERRNO!=EADDRINUSE) {
|
||||
ca_printf(
|
||||
"CA Repeater: bind test err was \"%s\"\n", strerror(SOCKERRNO));
|
||||
"CA Repeater: bind test err was %d=\"%s\"\n",
|
||||
SOCKERRNO, strerror(SOCKERRNO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
299
src/ca/service.c
299
src/ca/service.c
@@ -73,12 +73,6 @@ static char *sccsId = "@(#) $Id$";
|
||||
#include "iocinf.h"
|
||||
#include "net_convert.h"
|
||||
|
||||
|
||||
LOCAL void reconnect_channel(
|
||||
IIU *piiu,
|
||||
ciu chan
|
||||
);
|
||||
|
||||
LOCAL int cacMsg(
|
||||
struct ioc_in_use *piiu,
|
||||
const struct in_addr *pnet_addr
|
||||
@@ -338,13 +332,18 @@ const struct in_addr *pnet_addr
|
||||
* format to host format
|
||||
*
|
||||
*/
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
piiu->pCurData,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
# endif
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
if (piiu->curMsg.m_type<NELEMENTS(cac_dbr_cvrt)) {
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
piiu->pCurData,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
}
|
||||
else {
|
||||
piiu->curMsg.m_cid = htonl(ECA_BADTYPE);
|
||||
}
|
||||
# endif
|
||||
|
||||
args.usr = (void *) monix->usr_arg;
|
||||
args.chid = monix->chan;
|
||||
@@ -416,12 +415,17 @@ const struct in_addr *pnet_addr
|
||||
* convert the data buffer from net
|
||||
* format to host format
|
||||
*/
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
piiu->pCurData,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
if (piiu->curMsg.m_type<NELEMENTS(cac_dbr_cvrt)) {
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
piiu->pCurData,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
}
|
||||
else {
|
||||
piiu->curMsg.m_cid = htonl(ECA_BADTYPE);
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
@@ -483,33 +487,34 @@ const struct in_addr *pnet_addr
|
||||
* convert the data buffer from net
|
||||
* format to host format
|
||||
*/
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
(void *) pIOBlock->usr_arg,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
# else
|
||||
if (piiu->curMsg.m_type == DBR_STRING &&
|
||||
piiu->curMsg.m_count == 1u) {
|
||||
strcpy ((char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData);
|
||||
}
|
||||
else {
|
||||
memcpy(
|
||||
(char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData,
|
||||
dbr_size_n (
|
||||
piiu->curMsg.m_type,
|
||||
piiu->curMsg.m_count)
|
||||
);
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* decrement the outstanding IO count
|
||||
*/
|
||||
CLRPENDRECV;
|
||||
if (piiu->curMsg.m_type <= (unsigned) LAST_BUFFER_TYPE) {
|
||||
# ifdef CONVERSION_REQUIRED
|
||||
(*cac_dbr_cvrt[piiu->curMsg.m_type])(
|
||||
piiu->pCurData,
|
||||
(void *) pIOBlock->usr_arg,
|
||||
FALSE,
|
||||
piiu->curMsg.m_count);
|
||||
# else
|
||||
if (piiu->curMsg.m_type == DBR_STRING &&
|
||||
piiu->curMsg.m_count == 1u) {
|
||||
strcpy ((char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData);
|
||||
}
|
||||
else {
|
||||
memcpy(
|
||||
(char *)pIOBlock->usr_arg,
|
||||
piiu->pCurData,
|
||||
dbr_size_n (
|
||||
piiu->curMsg.m_type,
|
||||
piiu->curMsg.m_count)
|
||||
);
|
||||
}
|
||||
# endif
|
||||
/*
|
||||
* decrement the outstanding IO count
|
||||
*/
|
||||
CLRPENDRECV;
|
||||
}
|
||||
}
|
||||
LOCK;
|
||||
ellDelete(&pend_read_list, &pIOBlock->node);
|
||||
@@ -528,21 +533,33 @@ const struct in_addr *pnet_addr
|
||||
case CA_PROTO_RSRV_IS_UP:
|
||||
LOCK;
|
||||
{
|
||||
struct in_addr ina;
|
||||
struct sockaddr_in ina;
|
||||
|
||||
/*
|
||||
* this allows a fan-out server to potentially
|
||||
* insert the true address of a server
|
||||
* (servers prior to 3.13 always set this
|
||||
*
|
||||
* (servers always set this
|
||||
* field to one of the ip addresses of the host)
|
||||
* (clients prior to 3.13 always expect that this
|
||||
* (clients always expect that this
|
||||
* field is set to the server's IP address).
|
||||
*/
|
||||
ina.sin_family = AF_INET;
|
||||
if (piiu->curMsg.m_available != INADDR_ANY) {
|
||||
ina.s_addr = piiu->curMsg.m_available;
|
||||
ina.sin_addr.s_addr = piiu->curMsg.m_available;
|
||||
}
|
||||
else {
|
||||
ina = *pnet_addr;
|
||||
ina.sin_addr = *pnet_addr;
|
||||
}
|
||||
if (piiu->curMsg.m_count != 0) {
|
||||
ina.sin_port = htons (piiu->curMsg.m_count);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* old servers dont supply this and the
|
||||
* default port must be assumed
|
||||
*/
|
||||
ina.sin_port = htons (ca_static->ca_server_port);
|
||||
}
|
||||
mark_server_available(&ina);
|
||||
}
|
||||
@@ -728,7 +745,7 @@ const struct in_addr *pnet_addr
|
||||
if (CA_V44(CA_PROTOCOL_VERSION,piiu->minor_version_number)) {
|
||||
chan->id.sid = piiu->curMsg.m_available;
|
||||
}
|
||||
reconnect_channel(piiu, chan);
|
||||
cac_reconnect_channel(chan);
|
||||
break;
|
||||
}
|
||||
case CA_PROTO_CLAIM_CIU_FAILED:
|
||||
@@ -783,15 +800,17 @@ IIU *piiu,
|
||||
const struct in_addr *pnet_addr
|
||||
)
|
||||
{
|
||||
int v42;
|
||||
unsigned short port;
|
||||
char rej[64];
|
||||
ciu chan;
|
||||
int status;
|
||||
IIU *allocpiiu;
|
||||
IIU *chpiiu;
|
||||
unsigned short *pMinorVersion;
|
||||
unsigned minorVersion;
|
||||
struct sockaddr_in ina;
|
||||
char rej[64];
|
||||
ciu chan;
|
||||
int status;
|
||||
IIU *allocpiiu;
|
||||
unsigned short *pMinorVersion;
|
||||
unsigned minorVersion;
|
||||
|
||||
if (piiu!=piiuCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* ignore broadcast replies for deleted channels
|
||||
@@ -807,8 +826,7 @@ const struct in_addr *pnet_addr
|
||||
return;
|
||||
}
|
||||
|
||||
chpiiu = chan->piiu;
|
||||
if(!chpiiu){
|
||||
if(!chan->piiu){
|
||||
ca_printf("cast reply to local channel??\n");
|
||||
UNLOCK;
|
||||
return;
|
||||
@@ -822,30 +840,6 @@ const struct in_addr *pnet_addr
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore duplicate search replies
|
||||
*/
|
||||
if (chpiiu != piiuCast) {
|
||||
caAddrNode *pNode;
|
||||
|
||||
pNode = (caAddrNode *) chpiiu->destAddr.node.next;
|
||||
assert(pNode);
|
||||
if (pNode->destAddr.in.sin_addr.s_addr !=
|
||||
pnet_addr->s_addr) {
|
||||
|
||||
caHostFromInetAddr(pnet_addr,rej,sizeof(rej));
|
||||
sprintf(
|
||||
sprintf_buf,
|
||||
"Channel: %s Accepted: %s Rejected: %s ",
|
||||
(char *)(chan + 1),
|
||||
chpiiu->host_name_str,
|
||||
rej);
|
||||
genLocalExcep (ECA_DBLCHNL, sprintf_buf);
|
||||
}
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting with CA V4.1 the minor version number
|
||||
* is appended to the end of each search reply.
|
||||
@@ -863,13 +857,50 @@ const struct in_addr *pnet_addr
|
||||
* the type field is abused to carry the port number
|
||||
* so that we can have multiple servers on one host
|
||||
*/
|
||||
if (CA_V45 (CA_PROTOCOL_VERSION,minorVersion)) {
|
||||
port = piiu->curMsg.m_type;
|
||||
ina.sin_family = AF_INET;
|
||||
if (CA_V48 (CA_PROTOCOL_VERSION,minorVersion)) {
|
||||
if (piiu->curMsg.m_cid != ~0ul) {
|
||||
ina.sin_addr.s_addr = htonl(piiu->curMsg.m_cid);
|
||||
}
|
||||
else {
|
||||
ina.sin_addr = *pnet_addr;
|
||||
}
|
||||
ina.sin_port = htons(piiu->curMsg.m_type);
|
||||
}
|
||||
else if (CA_V45 (CA_PROTOCOL_VERSION,minorVersion)) {
|
||||
ina.sin_port = htons(piiu->curMsg.m_type);
|
||||
ina.sin_addr = *pnet_addr;
|
||||
}
|
||||
else {
|
||||
port = ca_static->ca_server_port;
|
||||
ina.sin_port = htons(ca_static->ca_server_port);
|
||||
ina.sin_addr = *pnet_addr;
|
||||
}
|
||||
status = alloc_ioc (pnet_addr, port, &allocpiiu);
|
||||
|
||||
/*
|
||||
* Ignore duplicate search replies
|
||||
*/
|
||||
if (piiuCast != (IIU *) chan->piiu) {
|
||||
caAddrNode *pNode;
|
||||
IIU *tcpPIIU = (IIU *) chan->piiu;
|
||||
|
||||
pNode = (caAddrNode *) ellFirst(&tcpPIIU->destAddr);
|
||||
assert(pNode);
|
||||
if (pNode->destAddr.in.sin_addr.s_addr != ina.sin_addr.s_addr ||
|
||||
pNode->destAddr.in.sin_port != ina.sin_port) {
|
||||
caHostFromInetAddr(pnet_addr,rej,sizeof(rej));
|
||||
sprintf(
|
||||
sprintf_buf,
|
||||
"Channel: %s Accepted: %s Rejected: %s ",
|
||||
(char *)(chan + 1),
|
||||
tcpPIIU->host_name_str,
|
||||
rej);
|
||||
genLocalExcep (ECA_DBLCHNL, sprintf_buf);
|
||||
}
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
status = alloc_ioc (&ina, &allocpiiu);
|
||||
switch (status) {
|
||||
|
||||
case ECA_NORMAL:
|
||||
@@ -897,30 +928,45 @@ const struct in_addr *pnet_addr
|
||||
|
||||
allocpiiu->minor_version_number = minorVersion;
|
||||
|
||||
ellDelete (&chpiiu->chidlist, &chan->node);
|
||||
chan->piiu = allocpiiu;
|
||||
ellAdd (&allocpiiu->chidlist, &chan->node);
|
||||
ca_static->ca_search_responses++;
|
||||
|
||||
/*
|
||||
* If this is the first channel to be
|
||||
* added to this IIU then communicate
|
||||
* the client's name to the server.
|
||||
* (CA V4.1 or higher)
|
||||
*/
|
||||
if (ellCount(&allocpiiu->chidlist)==1) {
|
||||
if (ellCount(&allocpiiu->chidlist)==0) {
|
||||
issue_identify_client(allocpiiu);
|
||||
issue_client_host_name(allocpiiu);
|
||||
}
|
||||
|
||||
/*
|
||||
* claim the resource in the IOC
|
||||
* over TCP so problems with duplicate UDP port
|
||||
* after reboot go away
|
||||
* increase the valid search response count only if this
|
||||
* response matches up with a request since the beginning
|
||||
* of the search list
|
||||
*/
|
||||
chan->id.sid = piiu->curMsg.m_cid;
|
||||
issue_claim_channel(allocpiiu, chan);
|
||||
if (ca_static->ca_seq_no_at_list_begin <= chan->retrySeqNo) {
|
||||
if (ca_static->ca_search_responses<ULONG_MAX) {
|
||||
ca_static->ca_search_responses++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove it from the broadcast IIU
|
||||
*/
|
||||
removeFromChanList(chan);
|
||||
|
||||
/*
|
||||
* chan->piiu must be correctly set prior to issuing the
|
||||
* claim request
|
||||
*
|
||||
* add to the beginning of the list until we
|
||||
* have sent the claim message (after which we
|
||||
* move it to the end of the list)
|
||||
*
|
||||
* claim pending flag is set here
|
||||
*/
|
||||
addToChanList(chan, allocpiiu);
|
||||
|
||||
/*
|
||||
* Assume that we have access once connected briefly
|
||||
* until the server is able to tell us the correct
|
||||
@@ -933,40 +979,53 @@ const struct in_addr *pnet_addr
|
||||
chan->ar.read_access = TRUE;
|
||||
chan->ar.write_access = TRUE;
|
||||
|
||||
UNLOCK;
|
||||
|
||||
v42 = CA_V42(
|
||||
CA_PROTOCOL_VERSION,
|
||||
allocpiiu->minor_version_number);
|
||||
if (!v42) {
|
||||
reconnect_channel(piiu, chan);
|
||||
/*
|
||||
* Reset the delay to the next search request if we get
|
||||
* at least one response. However, dont reset this delay if we
|
||||
* get a delayed response to an old search request.
|
||||
*/
|
||||
if (chan->retrySeqNo == ca_static->ca_search_retry_seq_no) {
|
||||
ca_static->ca_conn_next_retry = ca_static->currentTime;
|
||||
}
|
||||
|
||||
/*
|
||||
* claim the resource in the IOC
|
||||
* over TCP so problems with duplicate UDP port
|
||||
* after reboot go away
|
||||
*
|
||||
* if we cant immediately get buffer space then we
|
||||
* attempt to flush once and then try again.
|
||||
* If this fails then we will wait for the
|
||||
* next search response.
|
||||
*/
|
||||
chan->id.sid = piiu->curMsg.m_cid;
|
||||
UNLOCK
|
||||
issue_claim_channel(chan);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* reconnect_channel()
|
||||
* cac_reconnect_channel()
|
||||
*
|
||||
* LOCK must _not_ be applied
|
||||
*/
|
||||
LOCAL void reconnect_channel(
|
||||
IIU *piiu,
|
||||
ciu chan
|
||||
)
|
||||
void cac_reconnect_channel(ciu chan)
|
||||
{
|
||||
IIU *piiu = (IIU *) chan->piiu;
|
||||
evid pevent;
|
||||
enum channel_state prev_cs;
|
||||
int v41;
|
||||
|
||||
prev_cs = chan->state;
|
||||
if (prev_cs == cs_conn) {
|
||||
ca_printf("Ignored connect response to connected channel\n");
|
||||
ca_printf("CAC: Ignored conn resp to conn chan CID=%u SID=%u?\n",
|
||||
chan->cid, chan->id.sid);
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
|
||||
v41 = CA_V41(
|
||||
CA_PROTOCOL_VERSION,
|
||||
((IIU *)chan->piiu)->minor_version_number);
|
||||
v41 = CA_V41(CA_PROTOCOL_VERSION, piiu->minor_version_number);
|
||||
|
||||
/* Update rmt chid fields from caHdr fields */
|
||||
chan->type = piiu->curMsg.m_type;
|
||||
@@ -1031,7 +1090,9 @@ ciu chan
|
||||
UNLOCKEVENTS;
|
||||
}
|
||||
else if(prev_cs==cs_never_conn){
|
||||
/* decrement the outstanding IO count */
|
||||
/*
|
||||
* decrement the outstanding IO count
|
||||
*/
|
||||
CLRPENDRECV;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* Revision 1.23 1997/04/29 06:12:42 jhill
|
||||
* use free lists
|
||||
*
|
||||
* Revision 1.22 1996/11/22 19:08:02 jhill
|
||||
* added const to API
|
||||
*
|
||||
* Revision 1.21 1996/11/02 00:51:08 jhill
|
||||
* many pc port, const in API, and other changes
|
||||
*
|
||||
@@ -55,6 +61,7 @@
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "freeList.h"
|
||||
|
||||
LOCAL void io_complete(struct event_handler_args args);
|
||||
|
||||
@@ -67,8 +74,8 @@ void ca_sg_init(void)
|
||||
/*
|
||||
* init all sync group lists
|
||||
*/
|
||||
ellInit(&ca_static->activeCASG);
|
||||
ellInit(&ca_static->freeCASG);
|
||||
freeListInitPvt(&ca_static->ca_sgFreeListPVT,sizeof(CASG),32);
|
||||
freeListInitPvt(&ca_static->ca_sgopFreeListPVT,sizeof(CASGOP),256);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -77,7 +84,7 @@ void ca_sg_init(void)
|
||||
/*
|
||||
* ca_sg_shutdown()
|
||||
*/
|
||||
void ca_sg_shutdown(struct ca_static *ca_temp)
|
||||
void ca_sg_shutdown(struct CA_STATIC *ca_temp)
|
||||
{
|
||||
CASG *pcasg;
|
||||
CASG *pnextcasg;
|
||||
@@ -99,13 +106,13 @@ void ca_sg_shutdown(struct ca_static *ca_temp)
|
||||
/*
|
||||
* per sync group
|
||||
*/
|
||||
ellFree (&ca_temp->freeCASG);
|
||||
freeListCleanup(ca_temp->ca_sgFreeListPVT);
|
||||
|
||||
/*
|
||||
* per sync group op
|
||||
*/
|
||||
ellFree (&ca_temp->activeCASGOP);
|
||||
ellFree (&ca_temp->freeCASGOP);
|
||||
freeListCleanup(ca_temp->ca_sgopFreeListPVT);
|
||||
|
||||
UNLOCK;
|
||||
|
||||
@@ -132,15 +139,13 @@ int epicsShareAPI ca_sg_create(CA_SYNC_GID *pgid)
|
||||
* first look on a free list. If not there
|
||||
* allocate dynamic memory for it.
|
||||
*/
|
||||
LOCK;
|
||||
pcasg = (CASG *) ellGet(&ca_static->freeCASG);
|
||||
pcasg = (CASG *) freeListMalloc(ca_static->ca_sgFreeListPVT);
|
||||
if(!pcasg){
|
||||
pcasg = (CASG *) malloc(sizeof(*pcasg));
|
||||
if(!pcasg){
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* setup initial values for all of the fields
|
||||
*
|
||||
@@ -170,7 +175,7 @@ int epicsShareAPI ca_sg_create(CA_SYNC_GID *pgid)
|
||||
/*
|
||||
* place it back on the free sync group list
|
||||
*/
|
||||
ellAdd (&ca_static->freeCASG, &pcasg->node);
|
||||
freeListFree(ca_static->ca_sgFreeListPVT, pcasg);
|
||||
UNLOCK;
|
||||
if (status == S_bucket_noMemory) {
|
||||
return ECA_ALLOCMEM;
|
||||
@@ -217,10 +222,10 @@ int epicsShareAPI ca_sg_delete(const CA_SYNC_GID gid)
|
||||
|
||||
pcasg->magic = 0;
|
||||
ellDelete(&ca_static->activeCASG, &pcasg->node);
|
||||
ellAdd(&ca_static->freeCASG, &pcasg->node);
|
||||
|
||||
UNLOCK;
|
||||
|
||||
freeListFree(ca_static->ca_sgFreeListPVT, pcasg);
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
@@ -417,24 +422,21 @@ const void *pvalue)
|
||||
CASGOP *pcasgop;
|
||||
CASG *pcasg;
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
/*
|
||||
* first look on a free list. If not there
|
||||
* allocate dynamic memory for it.
|
||||
*/
|
||||
pcasgop = (CASGOP *)ellGet(&ca_static->freeCASGOP);
|
||||
pcasgop = (CASGOP *) freeListMalloc(ca_static->ca_sgopFreeListPVT);
|
||||
if(!pcasgop){
|
||||
pcasgop = (CASGOP *)malloc(sizeof(*pcasgop));
|
||||
if(!pcasgop){
|
||||
UNLOCK;
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
freeListFree(ca_static->ca_sgopFreeListPVT, pcasgop);
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
memset((char *)pcasgop, 0,sizeof(*pcasgop));
|
||||
@@ -459,8 +461,8 @@ const void *pvalue)
|
||||
assert(pcasg->opPendCount>=1u);
|
||||
pcasg->opPendCount--;
|
||||
ellDelete(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
ellAdd(&ca_static->freeCASGOP, &pcasgop->node);
|
||||
UNLOCK;
|
||||
freeListFree(ca_static->ca_sgopFreeListPVT, pcasgop);
|
||||
}
|
||||
|
||||
|
||||
@@ -483,24 +485,21 @@ void *pvalue)
|
||||
CASGOP *pcasgop;
|
||||
CASG *pcasg;
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
/*
|
||||
* first look on a free list. If not there
|
||||
* allocate dynamic memory for it.
|
||||
*/
|
||||
pcasgop = (CASGOP *)ellGet(&ca_static->freeCASGOP);
|
||||
pcasgop = (CASGOP *) freeListMalloc(ca_static->ca_sgopFreeListPVT);
|
||||
if(!pcasgop){
|
||||
pcasgop = (CASGOP *) malloc(sizeof(*pcasgop));
|
||||
if(!pcasgop){
|
||||
UNLOCK;
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
pcasg = bucketLookupItemUnsignedId(pSlowBucket, &gid);
|
||||
if(!pcasg || pcasg->magic != CASG_MAGIC){
|
||||
UNLOCK;
|
||||
freeListFree(ca_static->ca_sgopFreeListPVT, pcasgop);
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
memset((char *)pcasgop, 0,sizeof(*pcasgop));
|
||||
@@ -525,8 +524,8 @@ void *pvalue)
|
||||
assert(pcasg->opPendCount>=1u);
|
||||
pcasg->opPendCount--;
|
||||
ellDelete(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
ellAdd(&ca_static->freeCASGOP, &pcasgop->node);
|
||||
UNLOCK;
|
||||
freeListFree(ca_static->ca_sgopFreeListPVT, pcasgop);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -547,7 +546,6 @@ LOCAL void io_complete(struct event_handler_args args)
|
||||
LOCK;
|
||||
ellDelete(&ca_static->activeCASGOP, &pcasgop->node);
|
||||
pcasgop->magic = 0;
|
||||
ellAdd(&ca_static->freeCASGOP, &pcasgop->node);
|
||||
|
||||
/*
|
||||
* ignore stale replies
|
||||
@@ -567,6 +565,7 @@ LOCAL void io_complete(struct event_handler_args args)
|
||||
pcasgop->id,
|
||||
ca_message(args.status));
|
||||
UNLOCK;
|
||||
freeListFree(ca_static->ca_sgopFreeListPVT, pcasgop);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -587,6 +586,8 @@ LOCAL void io_complete(struct event_handler_args args)
|
||||
|
||||
UNLOCK;
|
||||
|
||||
freeListFree(ca_static->ca_sgopFreeListPVT, pcasgop);
|
||||
|
||||
/*
|
||||
* Wake up any tasks pending
|
||||
*
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
* cjm 20-Nov-95 Add code for gettimeofday
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.21 1997/01/22 21:11:49 jhill
|
||||
* moved vms includes here
|
||||
*
|
||||
* Revision 1.20 1996/07/02 23:04:07 jhill
|
||||
* took &tz out of gettimeofday()
|
||||
*
|
||||
@@ -164,7 +167,7 @@ void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
|
||||
/*
|
||||
* cac_os_depen_init()
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
int cac_os_depen_init(struct CA_STATIC *pcas)
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -179,7 +182,7 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
/*
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
void cac_os_depen_exit (struct CA_STATIC *pcas)
|
||||
{
|
||||
ca_static = pcas;
|
||||
ca_process_exit();
|
||||
|
||||
@@ -29,6 +29,18 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* Revision 1.30 1997/04/29 06:13:49 jhill
|
||||
* use free lists
|
||||
*
|
||||
* Revision 1.29 1997/04/23 17:05:10 jhill
|
||||
* pc port changes
|
||||
*
|
||||
* Revision 1.28 1997/04/10 19:26:19 jhill
|
||||
* asynch connect, faster connect, ...
|
||||
*
|
||||
* Revision 1.27 1996/11/02 00:51:10 jhill
|
||||
* many pc port, const in API, and other changes
|
||||
*
|
||||
* Revision 1.26 1996/09/16 16:39:20 jhill
|
||||
* local except => except handler
|
||||
*
|
||||
@@ -53,17 +65,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <callback.h>
|
||||
#include "callback.h"
|
||||
#include "iocinf.h"
|
||||
#include "remLib.h"
|
||||
#include "dbEvent.h"
|
||||
#include "freeList.h"
|
||||
|
||||
LOCAL void ca_repeater_task();
|
||||
LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb);
|
||||
LOCAL void ca_extra_event_labor(void *pArg);
|
||||
LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid);
|
||||
LOCAL int cac_add_task_variable (struct ca_static *ca_temp);
|
||||
LOCAL int cac_os_depen_exit_tid (struct CA_STATIC *pcas, int tid);
|
||||
LOCAL int cac_add_task_variable (struct CA_STATIC *ca_temp);
|
||||
LOCAL void deleteCallBack(CALLBACK *pcb);
|
||||
LOCAL void ca_check_for_fp();
|
||||
LOCAL int event_import(int tid);
|
||||
|
||||
/*
|
||||
* order of ops is important here
|
||||
@@ -226,7 +241,7 @@ void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
|
||||
/*
|
||||
* CAC_ADD_TASK_VARIABLE()
|
||||
*/
|
||||
LOCAL int cac_add_task_variable (struct ca_static *ca_temp)
|
||||
LOCAL int cac_add_task_variable (struct CA_STATIC *ca_temp)
|
||||
{
|
||||
static char ca_installed;
|
||||
TVIU *ptviu;
|
||||
@@ -302,7 +317,7 @@ LOCAL int cac_add_task_variable (struct ca_static *ca_temp)
|
||||
LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb)
|
||||
{
|
||||
int status;
|
||||
struct ca_static *ca_temp;
|
||||
struct CA_STATIC *ca_temp;
|
||||
|
||||
# ifdef DEBUG
|
||||
ca_printf("CAC: entering the exit handler %x\n", ptcb);
|
||||
@@ -315,9 +330,9 @@ LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb)
|
||||
* the task id - somthing which may not be true
|
||||
* on future releases of vxWorks
|
||||
*/
|
||||
ca_temp = (struct ca_static *)
|
||||
ca_temp = (struct CA_STATIC *)
|
||||
taskVarGet((int)ptcb, (int *) &ca_static);
|
||||
if (ca_temp == (struct ca_static *) ERROR){
|
||||
if (ca_temp == (struct CA_STATIC *) ERROR){
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -350,17 +365,19 @@ LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb)
|
||||
/*
|
||||
* cac_os_depen_init()
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
int cac_os_depen_init(struct CA_STATIC *pcas)
|
||||
{
|
||||
char name[15];
|
||||
int status;
|
||||
|
||||
ellInit(&pcas->ca_local_chidlist);
|
||||
ellInit(&pcas->ca_dbfree_ev_list);
|
||||
ellInit(&pcas->ca_lcl_buff_list);
|
||||
ellInit(&pcas->ca_taskVarList);
|
||||
ellInit(&pcas->ca_putNotifyQue);
|
||||
|
||||
freeListInitPvt(&pcas->ca_dbMonixFreeList,
|
||||
db_sizeof_event_block()+sizeof(struct pending_event),256);
|
||||
|
||||
pcas->ca_tid = taskIdSelf();
|
||||
pcas->ca_client_lock = semMCreate(SEM_DELETE_SAFE);
|
||||
assert(pcas->ca_client_lock);
|
||||
@@ -388,7 +405,7 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
assert(evuser);
|
||||
|
||||
status = db_add_extra_labor_event(
|
||||
evuser,
|
||||
(struct event_user *)evuser,
|
||||
ca_extra_event_labor,
|
||||
pcas);
|
||||
assert(status==0);
|
||||
@@ -398,9 +415,9 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
taskName(VXTHISTASKID),
|
||||
sizeof(name) - strlen(name) - 1);
|
||||
status = db_start_events(
|
||||
evuser,
|
||||
(struct event_user *)evuser,
|
||||
name,
|
||||
ca_import,
|
||||
event_import,
|
||||
taskIdSelf(),
|
||||
-1); /* higher priority */
|
||||
assert(status == OK);
|
||||
@@ -412,7 +429,7 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
/*
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
void cac_os_depen_exit (struct CA_STATIC *pcas)
|
||||
{
|
||||
cac_os_depen_exit_tid (pcas, 0);
|
||||
}
|
||||
@@ -421,7 +438,7 @@ void cac_os_depen_exit (struct ca_static *pcas)
|
||||
/*
|
||||
* cac_os_depen_exit_tid ()
|
||||
*/
|
||||
LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid)
|
||||
LOCAL int cac_os_depen_exit_tid (struct CA_STATIC *pcas, int tid)
|
||||
{
|
||||
int status;
|
||||
ciu chix;
|
||||
@@ -470,10 +487,10 @@ LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid)
|
||||
* can finish
|
||||
*/
|
||||
UNLOCK;
|
||||
status = db_cancel_event(monix + 1);
|
||||
status = db_cancel_event((struct event_block *)(monix+1));
|
||||
LOCK;
|
||||
assert(status == OK);
|
||||
free(monix);
|
||||
freeListFree (ca_static->ca_dbMonixFreeList, monix);
|
||||
}
|
||||
if (chix->ppn) {
|
||||
CACLIENTPUTNOTIFY *ppn;
|
||||
@@ -542,8 +559,7 @@ LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid)
|
||||
* remove local chid blocks, paddr blocks, waiting ev blocks
|
||||
*/
|
||||
ellFree(&pcas->ca_local_chidlist);
|
||||
ellFree(&pcas->ca_dbfree_ev_list);
|
||||
|
||||
freeListCleanup(pcas->ca_dbMonixFreeList);
|
||||
|
||||
/*
|
||||
* remove semaphores here so that ca_process_exit()
|
||||
@@ -627,6 +643,22 @@ unsigned size)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* event_import()
|
||||
*/
|
||||
LOCAL int event_import(int tid)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = ca_import(tid);
|
||||
if (status==ECA_NORMAL) {
|
||||
return OK;
|
||||
}
|
||||
else {
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CA_IMPORT()
|
||||
@@ -636,7 +668,7 @@ unsigned size)
|
||||
int ca_import(int tid)
|
||||
{
|
||||
int status;
|
||||
struct ca_static *pcas;
|
||||
struct CA_STATIC *pcas;
|
||||
TVIU *ptviu;
|
||||
|
||||
ca_check_for_fp();
|
||||
@@ -645,9 +677,9 @@ int ca_import(int tid)
|
||||
* just return success if they have already done
|
||||
* a ca import for this task
|
||||
*/
|
||||
pcas = (struct ca_static *)
|
||||
pcas = (struct CA_STATIC *)
|
||||
taskVarGet(taskIdSelf(), (int *)&ca_static);
|
||||
if (pcas != (struct ca_static *) ERROR){
|
||||
if (pcas != (struct CA_STATIC *) ERROR){
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
@@ -656,9 +688,9 @@ int ca_import(int tid)
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
|
||||
pcas = (struct ca_static *)
|
||||
pcas = (struct CA_STATIC *)
|
||||
taskVarGet(tid, (int *)&ca_static);
|
||||
if (pcas == (struct ca_static *) ERROR){
|
||||
if (pcas == (struct CA_STATIC *) ERROR){
|
||||
free(ptviu);
|
||||
return ECA_NOCACTX;
|
||||
}
|
||||
@@ -689,7 +721,7 @@ int ca_import_cancel(int tid)
|
||||
{
|
||||
int status;
|
||||
TVIU *ptviu;
|
||||
struct ca_static *pcas;
|
||||
struct CA_STATIC *pcas;
|
||||
|
||||
if (tid == taskIdSelf()) {
|
||||
pcas = NULL;
|
||||
@@ -701,9 +733,9 @@ int ca_import_cancel(int tid)
|
||||
/*
|
||||
* Attempt to attach to the specified context
|
||||
*/
|
||||
ca_static = (struct ca_static *)
|
||||
ca_static = (struct CA_STATIC *)
|
||||
taskVarGet(tid, (int *)&ca_static);
|
||||
if (ca_static == (struct ca_static *) ERROR){
|
||||
if (ca_static == (struct CA_STATIC *) ERROR){
|
||||
ca_static = pcas;
|
||||
return ECA_NOCACTX;
|
||||
}
|
||||
@@ -776,7 +808,7 @@ void ca_spawn_repeater()
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
if (status < 0){
|
||||
if (status==ERROR){
|
||||
SEVCHK(ECA_NOREPEATER, NULL);
|
||||
}
|
||||
}
|
||||
@@ -800,7 +832,7 @@ LOCAL void ca_extra_event_labor(void *pArg)
|
||||
{
|
||||
int status;
|
||||
CACLIENTPUTNOTIFY *ppnb;
|
||||
struct ca_static *pcas;
|
||||
struct CA_STATIC *pcas;
|
||||
struct event_handler_args args;
|
||||
|
||||
pcas = pArg;
|
||||
@@ -894,14 +926,32 @@ void cac_recv_task(int tid)
|
||||
cac_clean_iiu_list();
|
||||
|
||||
/*
|
||||
* first check for pending recv's with a
|
||||
* zero time out so that
|
||||
* 1) flow control works correctly (and)
|
||||
* 2) we queue up sends resulting from recvs properly
|
||||
*/
|
||||
while (TRUE) {
|
||||
LD_CA_TIME (0.0, &timeout);
|
||||
count = cac_select_io(&timeout, CA_DO_RECVS);
|
||||
if (count<=0) {
|
||||
break;
|
||||
}
|
||||
ca_process_input_queue();
|
||||
}
|
||||
|
||||
/*
|
||||
* flush out all pending io prior to blocking
|
||||
*
|
||||
* NOTE: this must be longer than one vxWorks
|
||||
* tick or we will infinite loop
|
||||
*/
|
||||
timeout.tv_usec = (4*USEC_PER_SEC)/sysClkRateGet();
|
||||
timeout.tv_usec = (4/*ticks*/ * USEC_PER_SEC)/sysClkRateGet();
|
||||
timeout.tv_sec = 0;
|
||||
count = cac_select_io(&timeout, CA_DO_RECVS);
|
||||
count = cac_select_io(&timeout,
|
||||
CA_DO_RECVS|CA_DO_SENDS);
|
||||
ca_process_input_queue();
|
||||
manage_conn(TRUE);
|
||||
manage_conn();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,18 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* Revision 1.27 1997/05/01 19:46:32 jhill
|
||||
* fixed unintialized variable bug
|
||||
*
|
||||
* Revision 1.26 1997/04/11 20:36:00 jhill
|
||||
* kay's perl branch
|
||||
*
|
||||
* Revision 1.25 1997/04/10 19:26:20 jhill
|
||||
* asynch connect, faster connect, ...
|
||||
*
|
||||
* Revision 1.24 1997/01/09 22:14:26 jhill
|
||||
* installed changes on hostBuild branch
|
||||
*
|
||||
* Revision 1.23.2.1 1996/11/25 16:29:18 jhill
|
||||
* stuct=>struct and added debug msg
|
||||
*
|
||||
@@ -47,24 +59,6 @@
|
||||
* Revision 1.20 1995/12/19 19:36:20 jhill
|
||||
* function prototype changes
|
||||
*
|
||||
* Revision 1.19 1995/11/29 19:15:42 jhill
|
||||
* added $Log$
|
||||
* added Revision 1.23.2.1 1996/11/25 16:29:18 jhill
|
||||
* added stuct=>struct and added debug msg
|
||||
* added
|
||||
* added Revision 1.23 1996/11/02 00:51:12 jhill
|
||||
* added many pc port, const in API, and other changes
|
||||
* added
|
||||
* added Revision 1.22 1996/09/16 16:40:13 jhill
|
||||
* added make EPICS version be the console title
|
||||
* added
|
||||
* added Revision 1.21 1996/08/05 19:20:29 jhill
|
||||
* added removed incorrect ver number
|
||||
* added
|
||||
* Revision 1.20 1995/12/19 19:36:20 jhill
|
||||
* function prototype changes
|
||||
* to the header
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -74,7 +68,7 @@
|
||||
#include <process.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include <epicsVersion.h>
|
||||
#include "epicsVersion.h"
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
@@ -156,22 +150,12 @@ void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
|
||||
/*
|
||||
* cac_os_depen_init()
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
int cac_os_depen_init(struct CA_STATIC *pcas)
|
||||
{
|
||||
int status;
|
||||
|
||||
ca_static = pcas;
|
||||
|
||||
/*
|
||||
* dont allow disconnect to terminate process
|
||||
* when running in UNIX enviroment
|
||||
*
|
||||
* allow error to be returned to sendto()
|
||||
* instead of handling disconnect at interrupt
|
||||
*/
|
||||
|
||||
/* signal(SIGPIPE,SIG_IGN); */
|
||||
|
||||
/* DllMain does most OS dependent init & cleanup */
|
||||
|
||||
status = ca_os_independent_init ();
|
||||
@@ -183,7 +167,7 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
/*
|
||||
* cac_os_depen_exit ()
|
||||
*/
|
||||
void cac_os_depen_exit (struct ca_static *pcas)
|
||||
void cac_os_depen_exit (struct CA_STATIC *pcas)
|
||||
{
|
||||
ca_static = pcas;
|
||||
ca_process_exit();
|
||||
@@ -492,7 +476,7 @@ BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
|
||||
int status;
|
||||
WSADATA WsaData;
|
||||
TIMECAPS tc;
|
||||
UINT wTimerRes;
|
||||
static UINT wTimerRes;
|
||||
|
||||
switch (dwReason) {
|
||||
|
||||
@@ -500,7 +484,7 @@ BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
|
||||
|
||||
#if _DEBUG /* for gui applications, setup console for error messages */
|
||||
if (AllocConsole()) {
|
||||
SetConsoleTitle(EPICS_VERSION_STRING);
|
||||
SetConsoleTitle(BASE_VERSION_STRING);
|
||||
freopen( "CONOUT$", "a", stderr );
|
||||
}
|
||||
#ifndef NO_PROCESS_MSG
|
||||
@@ -508,7 +492,8 @@ BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
|
||||
#endif
|
||||
#endif
|
||||
/* init. winsock */
|
||||
if ((status = WSAStartup(MAKEWORD(1,1), &WsaData)) != 0) {
|
||||
if ((status = WSAStartup(MAKEWORD(2,0), &WsaData)) != 0) {
|
||||
WSACleanup();
|
||||
fprintf(stderr,"Cant init winsock \n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -561,4 +546,3 @@ return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -118,3 +118,78 @@ The defaults in base class casPV implement identical behavior
|
||||
to the past if these routines are not supplied by the derived
|
||||
class.
|
||||
|
||||
Changes between epics 3.13 Beta 6 and 3.13 Beta ????
|
||||
|
||||
**** API Change ****
|
||||
|
||||
o The member function "casChannel::postEvent()" has been replaced by
|
||||
"casChannel::postAccessRightsEvent()". An access rights state change
|
||||
event is now posted to the client each time that
|
||||
"casChannel::postAccessRightsEvent()" is called.
|
||||
|
||||
o The virtual functions "casChannel::interestRegister()"
|
||||
and "casChannel::interestDelete()" have been eliminated.
|
||||
|
||||
o The constructor "caServer::caServer()" no-longer has an argument specifying
|
||||
the maximum PV name length. It also no longer has an argument specifying
|
||||
the maximum simultaneous IO operations. THIS IS LIKELY TO BREAK YOUR CODE
|
||||
BECAUSE THE FIRST TWO ARGUMENTS WERE REMOVED AND THERE ARE DEFAULT ARGUMENTS.
|
||||
This change was made because we would like to remove all limits on
|
||||
the PV name length (real or perceived). We also felt that if a server
|
||||
tool wishes to postpone an asynchronious IO operation then it
|
||||
should return S_casApp_postponeAsyncIO from caServer::pvExistTest() and
|
||||
caServer::createPV() (instead of relying on the server to keep track of
|
||||
the number of simultaneous asynchronous IO operations). This provides a
|
||||
less complex and more flexible API.
|
||||
|
||||
o The member function "casPV::casPV(caServer &cas)" replaces the member
|
||||
function "casPV::casPV(const casCtx &ctx, const char * const pPVName)".
|
||||
|
||||
o The virtual member function
|
||||
"caServer::createPV(const casCtx &ctx, const char *pPVName)"
|
||||
has been replaced by the virtual member function
|
||||
"pvCreateReturn createPV (const casCtx &ctx, const char *pPVAliasName)"
|
||||
This change was made in order to allow asynchronous completion of a
|
||||
PV create operation.
|
||||
|
||||
o The data type (class) pvExistReturn has been changed to an enum -
|
||||
"enum pvExistReturn {pverExistsHere, pverDoesNotExistHere,
|
||||
pverAsyncCompletion, pverNoMemoryForAsyncOP}"
|
||||
This impacts the virtual member function
|
||||
"pvExistTest (const casCtx &ctx, const char *pPVAliasName)"
|
||||
|
||||
o The server tool is now required to supply the virtual function
|
||||
"casPV::getName()" so that the server is able to identify the process
|
||||
variable when diagnostics are printed.
|
||||
|
||||
o The virtual function casPV::maxSimultAsyncOps() has been eliminated
|
||||
in favor of allowing the server tool to return S_casApp_postponeAsyncIO
|
||||
from casPV::read() or casPV::write() when there are too many simultaneous
|
||||
asynchronous IO operations and the server tool would like to postpone
|
||||
the current (and future) request(s) until one of the outstanding asynchronous
|
||||
IO operations (read or write) completes.
|
||||
|
||||
o All "show()" virtual member functions in the interface classes
|
||||
have had the "const" attribute added.
|
||||
|
||||
**** Semantic Change ****
|
||||
|
||||
o IMPORTANT: It is now the responsibility of the server tool to detect attempts
|
||||
by the server lib to create a 2nd PV with the same canonical name as an
|
||||
existing PV and avoid this by returning a pointer to the first PV created.
|
||||
Likewise, if there are several aliases for one canonical PV name then it is
|
||||
the responsibility of the server tool to return "pvExistsHere" from
|
||||
"caServerDerived::pvExistTest()" for each of the aliases. Likewise, if there
|
||||
are several aliases for one canonical PV name then it is the responsibility
|
||||
of the server tool to return a single PV with the canonical name from
|
||||
"caServerDerived::createPV()" (even if createPV() is called multiple times
|
||||
each with a different alias name). This change was made to simplify the API
|
||||
and to eliminate redundant data structures and labor occurring within the server
|
||||
tool and the server library.
|
||||
|
||||
o PV creation is now allowed to complete asynchronously
|
||||
|
||||
o It is now the responsibility of the server tool to limit the
|
||||
number of simultaneous asynchronous IO operations allowed (by returning
|
||||
S_casApp_postponeAsyncIO).
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ include $(TOP)/config/CONFIG_BASE
|
||||
CXXCMPLR = STRICT
|
||||
|
||||
# sometimes it's good to have different C/C++ flags, not now:
|
||||
USR_CFLAGS = -I$(SRC) -I$(IOSRC) -I$(STSRC) -I$(CA)
|
||||
USR_CFLAGS = -I$(SRC) -I$(IOSRC) -I$(STSRC) -I$(CA) -DcaNetAddrSock
|
||||
USR_CXXFLAGS = $(USR_CFLAGS)
|
||||
|
||||
LIBSRCS += caServer.cc
|
||||
@@ -34,10 +34,10 @@ LIBSRCS += casAsyncXXIO.cc
|
||||
LIBSRCS += casAsyncRdIOI.cc
|
||||
LIBSRCS += casAsyncWtIOI.cc
|
||||
LIBSRCS += casAsyncExIOI.cc
|
||||
LIBSRCS += casAsyncPVCIOI.cc
|
||||
LIBSRCS += casEventSys.cc
|
||||
LIBSRCS += casMonitor.cc
|
||||
LIBSRCS += casMonEvent.cc
|
||||
LIBSRCS += casOpaqueAddr.cc
|
||||
LIBSRCS += inBuf.o
|
||||
LIBSRCS += outBuf.cc
|
||||
LIBSRCS += dgInBuf.o
|
||||
@@ -58,7 +58,6 @@ LIBSRCS += casIntfIO.cc
|
||||
LIBSRCS += casDGIntfIO.cc
|
||||
LIBSRCS += casDGIO.cc
|
||||
LIBSRCS += casStreamIO.cc
|
||||
LIBSRCS += sigPipeIgnore.c
|
||||
|
||||
LIBRARY := cas
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ TOP=../../..
|
||||
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
DIRS = simple
|
||||
DIRS = simple directoryService
|
||||
|
||||
include $(TOP)/config/RULES_DIRS
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
|
||||
This directory contains several server tool examples (which
|
||||
use the ca server library). The original ca server example
|
||||
is in the "simple" subdirectory.
|
||||
use the ca server library).
|
||||
|
||||
simple - complete CA server example (includes asynchronous
|
||||
io and arrays)
|
||||
|
||||
testdb - very simple ca server (does not provide some of the
|
||||
pv attributes (ie precision and others))
|
||||
|
||||
directoryService - fully functional pv name resolution server
|
||||
|
||||
|
||||
|
||||
7
src/cas/example/directoryService/Makefile
Normal file
7
src/cas/example/directoryService/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
TOP=../../../..
|
||||
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
include $(TOP)/config/RULES_ARCHS
|
||||
|
||||
27
src/cas/example/directoryService/Makefile.Host
Normal file
27
src/cas/example/directoryService/Makefile.Host
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
CAS = ../../..
|
||||
TOP = $(CAS)/../..
|
||||
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
CXXCMPLR = STRICT
|
||||
|
||||
PROD_LIBS := cas ca gdd Com
|
||||
|
||||
SRCS += main.cc
|
||||
SRCS += directoryServer.cc
|
||||
SRCS += templInst.cc
|
||||
|
||||
PROD := caDirServ
|
||||
|
||||
include $(TOP)/config/RULES.Host
|
||||
|
||||
pcaDirServ: $(PROD_OBJS) $(PRODDEPLIBS)
|
||||
$(PURIFY) $(PROD_LINKER) $(PROD_OBJS) $(LDLIBS)
|
||||
|
||||
clean::
|
||||
@$(RM) caDirServ
|
||||
@$(RM) pcaDirServ
|
||||
@$(RM) -rf Templates.DB
|
||||
@$(RM) core
|
||||
|
||||
38
src/cas/example/directoryService/Makefile.Vx.WorkInProgress
Normal file
38
src/cas/example/directoryService/Makefile.Vx.WorkInProgress
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
CAS = ../../..
|
||||
TOP = $(CAS)/../..
|
||||
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
CXXCMPLR = STRICT
|
||||
|
||||
USR_INCLUDES =
|
||||
USR_LDFLAGS =
|
||||
|
||||
DEPLIBS_BASE = $(EPICS_BASE_LIB)
|
||||
DEPLIBS = $(DEPLIBS_BASE)/libcas.a $(DEPLIBSWOCAS)
|
||||
|
||||
SRCS.cc += ../vxEntry.cc
|
||||
SRCS.cc += ../exServer.cc
|
||||
SRCS.cc += ../exPV.cc
|
||||
SRCS.cc += ../exSyncPV.cc
|
||||
SRCS.cc += ../exAsyncPV.cc
|
||||
SRCS.cc += ../exChannel.cc
|
||||
|
||||
LIBOBJS += vxEntry.o
|
||||
LIBOBJS += exServer.o
|
||||
LIBOBJS += exPV.o
|
||||
LIBOBJS += exSyncPV.o
|
||||
LIBOBJS += exAsyncPV.o
|
||||
LIBOBJS += exChannel.o
|
||||
|
||||
LIBNAME = libexserver.o
|
||||
include $(TOP)/config/RULES.Vx
|
||||
|
||||
excas: $(OBJS) $(DEPLIBS)
|
||||
$(LINK.cc) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
clean::
|
||||
@$(RM) -rf Templates.DB
|
||||
@$(RM) core
|
||||
|
||||
13
src/cas/example/directoryService/README
Normal file
13
src/cas/example/directoryService/README
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
This directory contains an example ca directory (name resolution) server.
|
||||
|
||||
The directory server reads in a file with records as follows:
|
||||
<PV name> <host name or dotted ip address> [<optional IP port number>]
|
||||
|
||||
The server responds to search requests with the true server address of
|
||||
the PV (not the address of this directory server).
|
||||
|
||||
This server can be used to cause EPICS to locate any PV listed in
|
||||
the file anywhere on the internet. You must of course set EPICS_CA_ADDR_LIST
|
||||
for the client so that it points at a running instance of this directory
|
||||
(name resolution) server.
|
||||
155
src/cas/example/directoryService/directoryServer.cc
Normal file
155
src/cas/example/directoryService/directoryServer.cc
Normal file
@@ -0,0 +1,155 @@
|
||||
|
||||
//
|
||||
// Example EPICS CA directory server
|
||||
//
|
||||
|
||||
#include "directoryServer.h"
|
||||
#include "tsMinMax.h"
|
||||
|
||||
const pvInfo *pvInfo::pFirst;
|
||||
|
||||
//
|
||||
// directoryServer::directoryServer()
|
||||
//
|
||||
directoryServer::directoryServer(const char * const pvPrefix, unsigned pvCount, unsigned aliasCount) :
|
||||
caServer(pvCount*(aliasCount+1u))
|
||||
{
|
||||
unsigned i;
|
||||
const pvInfo *pPVI;
|
||||
int resLibStatus;
|
||||
char pvAlias[256];
|
||||
const char * const pNameFmtStr = "%.100s%.20s";
|
||||
const char * const pAliasFmtStr = "%.100s%.20s%u";
|
||||
|
||||
//
|
||||
// hash table size may need adjustment here?
|
||||
//
|
||||
resLibStatus = this->stringResTbl.init(pvCount*(aliasCount+1u));
|
||||
if (resLibStatus) {
|
||||
fprintf(stderr, "CAS: string resource id table init failed\n");
|
||||
//
|
||||
// should throw an exception once this is portable
|
||||
//
|
||||
assert(resLibStatus==0);
|
||||
}
|
||||
|
||||
//
|
||||
// pre-create all of the simple PVs that this server will export
|
||||
//
|
||||
for (pPVI = pvInfo::getFirst(); pPVI; pPVI=pPVI->getNext()) {
|
||||
|
||||
//
|
||||
// Install canonical (root) name
|
||||
//
|
||||
sprintf(pvAlias, pNameFmtStr, pvPrefix, pPVI->getName());
|
||||
this->installAliasName(*pPVI, pvAlias);
|
||||
|
||||
//
|
||||
// Install numbered alias names
|
||||
//
|
||||
for (i=0u; i<aliasCount; i++) {
|
||||
sprintf(pvAlias, pAliasFmtStr, pvPrefix,
|
||||
pPVI->getName(), i);
|
||||
this->installAliasName(*pPVI, pvAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// directoryServer::installAliasName()
|
||||
//
|
||||
void directoryServer::installAliasName(const pvInfo &info, const char *pAliasName)
|
||||
{
|
||||
pvEntry *pEntry;
|
||||
|
||||
pEntry = new pvEntry(info, *this, pAliasName);
|
||||
if (pEntry) {
|
||||
int resLibStatus;
|
||||
resLibStatus = this->stringResTbl.add(*pEntry);
|
||||
if (resLibStatus==0) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
delete pEntry;
|
||||
}
|
||||
}
|
||||
fprintf(stderr,
|
||||
"Unable to enter PV=\"%s\" Alias=\"%s\" in PV name alias hash table\n",
|
||||
info.getName(), pAliasName);
|
||||
}
|
||||
|
||||
//
|
||||
// directoryServer::pvExistTest()
|
||||
//
|
||||
pvExistReturn directoryServer::pvExistTest
|
||||
(const casCtx&, const char *pPVName)
|
||||
{
|
||||
//
|
||||
// lifetime of id is shorter than lifetime of pName
|
||||
//
|
||||
char pvNameBuf[512];
|
||||
stringId id(pPVName, stringId::refString);
|
||||
stringId idBuf(pvNameBuf, stringId::refString);
|
||||
pvEntry *pPVE;
|
||||
const char *pStr, *pLastStr;
|
||||
|
||||
//
|
||||
// strip trailing occurrence of ".field"
|
||||
// (for compatibility with EPICS
|
||||
// function block database).
|
||||
//
|
||||
pStr = pPVName;
|
||||
do {
|
||||
pLastStr = pStr;
|
||||
pStr = strstr (pStr, ".");
|
||||
}
|
||||
while (pStr);
|
||||
|
||||
if (pLastStr==pPVName) {
|
||||
pPVE = this->stringResTbl.lookup(id);
|
||||
if (!pPVE) {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t diff = pLastStr-pPVName;
|
||||
diff = tsMin (diff, sizeof(pvNameBuf)-1);
|
||||
memcpy (pvNameBuf, pPVName, diff);
|
||||
pvNameBuf[diff] = '\0';
|
||||
pLastStr = pvNameBuf;
|
||||
pPVE = this->stringResTbl.lookup(idBuf);
|
||||
if (!pPVE) {
|
||||
//
|
||||
// look for entire PV name (in case this PV isnt
|
||||
// associated a function block database)
|
||||
//
|
||||
// lifetime of id2 is shorter than lifetime of pName
|
||||
//
|
||||
pPVE = this->stringResTbl.lookup(id);
|
||||
if (!pPVE) {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pvExistReturn (caNetAddr(pPVE->getInfo().getAddr()));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// directoryServer::show()
|
||||
//
|
||||
void directoryServer::show (unsigned level) const
|
||||
{
|
||||
//
|
||||
// server tool specific show code goes here
|
||||
//
|
||||
this->stringResTbl.show(level);
|
||||
|
||||
//
|
||||
// print information about ca server libarary
|
||||
// internals
|
||||
//
|
||||
this->caServer::show(level);
|
||||
}
|
||||
|
||||
135
src/cas/example/directoryService/directoryServer.h
Normal file
135
src/cas/example/directoryService/directoryServer.h
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// Example EPICS CA directory server
|
||||
//
|
||||
//
|
||||
// caServer
|
||||
// |
|
||||
// directoryServer
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// ANSI C
|
||||
//
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#include "epicsAssert.h"
|
||||
#define caNetAddrSock
|
||||
#include "casdef.h"
|
||||
#include "resourceLib.h"
|
||||
|
||||
|
||||
#ifndef NELEMENTS
|
||||
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
|
||||
#endif
|
||||
|
||||
class directoryServer;
|
||||
|
||||
//
|
||||
// pvInfo
|
||||
//
|
||||
class pvInfo {
|
||||
public:
|
||||
pvInfo (const char *pNameIn, sockaddr_in addrIn) :
|
||||
addr(addrIn), pNext(pvInfo::pFirst)
|
||||
{
|
||||
pvInfo::pFirst = this;
|
||||
this->pName = new char [strlen(pNameIn)+1u];
|
||||
assert(this->pName);
|
||||
strcpy(this->pName, pNameIn);
|
||||
}
|
||||
|
||||
const struct sockaddr_in getAddr() const { return this->addr; }
|
||||
const char *getName () const { return this->pName; }
|
||||
const pvInfo *getNext () const { return this->pNext; }
|
||||
static const pvInfo *getFirst () { return pvInfo::pFirst; }
|
||||
private:
|
||||
struct sockaddr_in addr;
|
||||
char *pName;
|
||||
const pvInfo *pNext;
|
||||
static const pvInfo *pFirst;
|
||||
};
|
||||
|
||||
//
|
||||
// pvEntry
|
||||
//
|
||||
// o entry in the string hash table for the pvInfo
|
||||
// o Since there may be aliases then we may end up
|
||||
// with several of this class all referencing
|
||||
// the same pv info class (justification
|
||||
// for this breaking out into a seperate class
|
||||
// from pvInfo)
|
||||
//
|
||||
class pvEntry : public stringId, public tsSLNode<pvEntry> {
|
||||
public:
|
||||
pvEntry (const pvInfo &infoIn, directoryServer &casIn,
|
||||
const char *pAliasName) :
|
||||
stringId(pAliasName), info(infoIn), cas(casIn)
|
||||
{
|
||||
assert(this->stringId::resourceName()!=NULL);
|
||||
}
|
||||
|
||||
inline ~pvEntry();
|
||||
|
||||
const pvInfo &getInfo() const { return this->info; }
|
||||
|
||||
inline void destroy ();
|
||||
|
||||
private:
|
||||
const pvInfo &info;
|
||||
directoryServer &cas;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// directoryServer
|
||||
//
|
||||
class directoryServer : public caServer {
|
||||
public:
|
||||
directoryServer (const char * const pvPrefix, unsigned pvCount, unsigned aliasCount);
|
||||
void show (unsigned level) const;
|
||||
pvExistReturn pvExistTest (const casCtx&, const char *pPVName);
|
||||
|
||||
void installAliasName (const pvInfo &info, const char *pAliasName);
|
||||
inline void removeAliasName(pvEntry &entry);
|
||||
|
||||
private:
|
||||
resTable<pvEntry,stringId> stringResTbl;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// directoryServer::removeAliasName()
|
||||
//
|
||||
inline void directoryServer::removeAliasName(pvEntry &entry)
|
||||
{
|
||||
pvEntry *pE;
|
||||
pE = this->stringResTbl.remove(entry);
|
||||
assert(pE = &entry);
|
||||
}
|
||||
|
||||
//
|
||||
// pvEntry::~pvEntry()
|
||||
//
|
||||
inline pvEntry::~pvEntry()
|
||||
{
|
||||
this->cas.removeAliasName(*this);
|
||||
}
|
||||
|
||||
//
|
||||
// pvEntry::destroy()
|
||||
//
|
||||
inline void pvEntry::destroy ()
|
||||
{
|
||||
//
|
||||
// always created with new
|
||||
//
|
||||
delete this;
|
||||
}
|
||||
|
||||
215
src/cas/example/directoryService/main.cc
Normal file
215
src/cas/example/directoryService/main.cc
Normal file
@@ -0,0 +1,215 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "directoryServer.h"
|
||||
#include "fdManager.h"
|
||||
|
||||
#define LOCAL static
|
||||
|
||||
LOCAL int parseDirectoryFile (const char *pFileName);
|
||||
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName);
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE (~0ul)
|
||||
#endif
|
||||
|
||||
//
|
||||
// main()
|
||||
// (example single threaded ca server tool main loop)
|
||||
//
|
||||
extern int main (int argc, const char **argv)
|
||||
{
|
||||
osiTime begin(osiTime::getCurrent());
|
||||
directoryServer *pCAS;
|
||||
unsigned debugLevel = 0u;
|
||||
float executionTime;
|
||||
char pvPrefix[128] = "";
|
||||
char fileName[128] = "pvDirectory.txt";
|
||||
unsigned aliasCount = 0u;
|
||||
aitBool forever = aitTrue;
|
||||
int nPV;
|
||||
int i;
|
||||
|
||||
for (i=1; i<argc; i++) {
|
||||
if (sscanf(argv[i], "-d %u", &debugLevel)==1) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-t %f", &executionTime)==1) {
|
||||
forever = aitFalse;
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-p %127s", pvPrefix)==1) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-c %u", &aliasCount)==1) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i], "-f %127s", fileName)==1) {
|
||||
continue;
|
||||
}
|
||||
fprintf (stderr,
|
||||
"usage: %s [-d<debug level> -t<execution time> -p<PV name prefix> -c<numbered alias count> -f<PV directory file>]\n",
|
||||
argv[0]);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
nPV = parseDirectoryFile (fileName);
|
||||
if (nPV<=0) {
|
||||
fprintf(stderr,
|
||||
"No PVs in directory file=%s. Exiting because there is no useful work to do.\n",
|
||||
fileName);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pCAS = new directoryServer(pvPrefix, (unsigned) nPV, aliasCount);
|
||||
if (!pCAS) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pCAS->setDebugLevel(debugLevel);
|
||||
|
||||
if (forever) {
|
||||
osiTime delay(1000u,0u);
|
||||
//
|
||||
// loop here forever
|
||||
//
|
||||
while (aitTrue) {
|
||||
fileDescriptorManager.process(delay);
|
||||
}
|
||||
}
|
||||
else {
|
||||
osiTime total(executionTime);
|
||||
osiTime delay(osiTime::getCurrent() - begin);
|
||||
//
|
||||
// loop here untime the specified execution time
|
||||
// expires
|
||||
//
|
||||
while (delay < total) {
|
||||
fileDescriptorManager.process(delay);
|
||||
delay = osiTime::getCurrent() - begin;
|
||||
}
|
||||
}
|
||||
pCAS->show(2u);
|
||||
delete pCAS;
|
||||
return (0);
|
||||
}
|
||||
|
||||
//
|
||||
// parseDirectoryFile()
|
||||
//
|
||||
// PV directory file is expected to have entries of the form:
|
||||
// <PV name> <host name or dotted ip address> [<optional IP port number>]
|
||||
//
|
||||
//
|
||||
LOCAL int parseDirectoryFile (const char *pFileName)
|
||||
{
|
||||
|
||||
FILE *pf;
|
||||
int nPV;
|
||||
|
||||
//
|
||||
// open a file that contains the PV directory
|
||||
//
|
||||
pf = fopen(pFileName, "r");
|
||||
if (!pf) {
|
||||
fprintf(stderr, "Directory file access probems with file=\"%s\" because \"%s\"\n",
|
||||
pFileName, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
nPV = parseDirectoryFP (pf, pFileName);
|
||||
|
||||
fclose (pf);
|
||||
|
||||
return nPV;
|
||||
}
|
||||
|
||||
//
|
||||
// parseDirectoryFP()
|
||||
//
|
||||
// PV directory file is expected to have entries of the form:
|
||||
// <PV name> <host name or dotted ip address> [<optional IP port number>]
|
||||
//
|
||||
//
|
||||
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
{
|
||||
pvInfo *pPVI;
|
||||
char pvNameStr[128];
|
||||
struct sockaddr_in ipa;
|
||||
char hostNameStr[128];
|
||||
int nPV=0;
|
||||
|
||||
ipa.sin_family = AF_INET;
|
||||
while (TRUE) {
|
||||
|
||||
//
|
||||
// parse the PV name entry from the file
|
||||
//
|
||||
if (fscanf(pf, " %127s ", pvNameStr) != 1) {
|
||||
return nPV; // success
|
||||
}
|
||||
|
||||
//
|
||||
// parse out server address
|
||||
//
|
||||
if (fscanf(pf, " %s ", hostNameStr) == 1) {
|
||||
|
||||
ipa.sin_addr.s_addr = inet_addr(hostNameStr);
|
||||
if (ipa.sin_addr.s_addr==INADDR_NONE) {
|
||||
struct hostent *pent;
|
||||
|
||||
pent = gethostbyname(hostNameStr);
|
||||
if (!pent) {
|
||||
fprintf (pf, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
|
||||
hostNameStr, pFileName, pvNameStr);
|
||||
return -1;
|
||||
}
|
||||
if (pent->h_addrtype != AF_INET) {
|
||||
fprintf (pf, "Unknown addr type for host=\"%s\" in \"%s\" with PV=\"%s\" addr type=%u?\n",
|
||||
hostNameStr, pFileName, pvNameStr, pent->h_addrtype);
|
||||
return -1;
|
||||
}
|
||||
assert (pent->h_addr_list[0]);
|
||||
assert (pent->h_length==sizeof(ipa.sin_addr));
|
||||
|
||||
memcpy ((char *)&ipa.sin_addr, pent->h_addr_list[0], pent->h_length);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf (stderr,"No host name (or dotted ip addr) after PV name in \"%s\" with PV=\"%s\"?\n",
|
||||
pFileName, pvNameStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// parse out optional IP port number
|
||||
//
|
||||
unsigned portNumber;
|
||||
if (fscanf(pf, " %u ", &portNumber) == 1) {
|
||||
if (portNumber>0xffff) {
|
||||
fprintf (stderr,"Port number supplied is to large in \"%s\" with PV=\"%s\" host=\"%s\" port=%u?\n",
|
||||
pFileName, pvNameStr, hostNameStr, portNumber);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipa.sin_port = (aitUint16) portNumber;
|
||||
}
|
||||
else {
|
||||
ipa.sin_port = 0u; // will default to this server's port
|
||||
}
|
||||
|
||||
pPVI = new pvInfo (pvNameStr, ipa);
|
||||
if (!pPVI) {
|
||||
fprintf (stderr, "Unable to allocate space for a new PV in \"%s\" with PV=\"%s\" host=\"%s\"\n",
|
||||
pFileName, pvNameStr, hostNameStr);
|
||||
return -1;
|
||||
}
|
||||
nPV++;
|
||||
}
|
||||
}
|
||||
5
src/cas/example/directoryService/pvDirectory.txt
Normal file
5
src/cas/example/directoryService/pvDirectory.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
ca:ai_2000 ioc3.atdiv.lanl.gov 22000
|
||||
ca:ai_2001 128.165.32.83 22000
|
||||
ca:ao_2000 ioc3
|
||||
ca:ao_2001 128.165.32.83
|
||||
27
src/cas/example/directoryService/templInst.cc
Normal file
27
src/cas/example/directoryService/templInst.cc
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Explcit instantiation of template instances used by the
|
||||
// example server
|
||||
//
|
||||
//
|
||||
|
||||
#include "directoryServer.h"
|
||||
#include "resourceLib.cc"
|
||||
|
||||
//
|
||||
// if the compiler supports explicit instantiation of
|
||||
// template member functions
|
||||
//
|
||||
#if defined(EXPL_TEMPL)
|
||||
//
|
||||
// From Stroustrups's "The C++ Programming Language"
|
||||
// Appendix A: r.14.9
|
||||
//
|
||||
// This explicitly instantiates the template class's
|
||||
// member functions into "templInst.o"
|
||||
//
|
||||
template class resTable <pvEntry,stringId>;
|
||||
#endif
|
||||
|
||||
844
src/cas/example/directoryService/test.adl
Normal file
844
src/cas/example/directoryService/test.adl
Normal file
@@ -0,0 +1,844 @@
|
||||
file {
|
||||
name="test.dl"
|
||||
}
|
||||
display {
|
||||
magic="305419896"
|
||||
majv="2"
|
||||
mnrv="4"
|
||||
ndyng="0"
|
||||
npc="5"
|
||||
nstr="8"
|
||||
ndynamic="12"
|
||||
nplot="0"
|
||||
nrd="0"
|
||||
nes="0"
|
||||
nkd="0"
|
||||
object {
|
||||
x="0"
|
||||
y="0"
|
||||
width="421"
|
||||
height="306"
|
||||
}
|
||||
clr="0"
|
||||
bclr="1"
|
||||
nwords_dspy="1106"
|
||||
nwords_sta="28"
|
||||
nwords_cmap="36"
|
||||
nwords_crules="106"
|
||||
odyng="306"
|
||||
osta="278"
|
||||
odynamic="306"
|
||||
oplot="1106"
|
||||
ord="1106"
|
||||
oes="1106"
|
||||
okd="1106"
|
||||
opc="58"
|
||||
ostr="88"
|
||||
ocmap="136"
|
||||
ocrules="172"
|
||||
style="solid"
|
||||
fill="outline"
|
||||
width="0"
|
||||
clrmod="static"
|
||||
vismod="static"
|
||||
clrrule="alarm"
|
||||
pv=""
|
||||
cmap=""
|
||||
}
|
||||
"<<color map>>" {
|
||||
ncolors="8"
|
||||
dl_color {
|
||||
r="255"
|
||||
g="255"
|
||||
b="255"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="128"
|
||||
}
|
||||
dl_color {
|
||||
r="0"
|
||||
g="0"
|
||||
b="0"
|
||||
inten="0"
|
||||
blink="off"
|
||||
RISCpad="75"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="0"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="-14684"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="0"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="on"
|
||||
RISCpad="14744"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="255"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="-16536"
|
||||
}
|
||||
dl_color {
|
||||
r="255"
|
||||
g="255"
|
||||
b="0"
|
||||
inten="255"
|
||||
blink="on"
|
||||
RISCpad="-15536"
|
||||
}
|
||||
dl_color {
|
||||
r="0"
|
||||
g="0"
|
||||
b="255"
|
||||
inten="255"
|
||||
blink="off"
|
||||
RISCpad="-28408"
|
||||
}
|
||||
dl_color {
|
||||
r="0"
|
||||
g="0"
|
||||
b="255"
|
||||
inten="255"
|
||||
blink="on"
|
||||
RISCpad="0"
|
||||
}
|
||||
}
|
||||
"<<color rules>>" {
|
||||
nrules="1"
|
||||
dl_color_rule {
|
||||
name="alarm"
|
||||
info[0] {
|
||||
chan="$(C).SEVR"
|
||||
value="MAJOR"
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="2"
|
||||
RISCpad="0"
|
||||
}
|
||||
info[1] {
|
||||
chan="$(C).SEVR"
|
||||
value="MINOR"
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="4"
|
||||
RISCpad="127"
|
||||
}
|
||||
info[2] {
|
||||
chan="$(C).SEVR"
|
||||
value="INFO"
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="6"
|
||||
RISCpad="44"
|
||||
}
|
||||
info[3] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-128"
|
||||
}
|
||||
info[4] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-1"
|
||||
}
|
||||
info[5] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-104"
|
||||
}
|
||||
info[6] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-1"
|
||||
}
|
||||
info[7] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="8"
|
||||
}
|
||||
info[8] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="120"
|
||||
}
|
||||
info[9] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="1"
|
||||
}
|
||||
info[10] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="7"
|
||||
}
|
||||
info[11] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="19"
|
||||
}
|
||||
info[12] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="48"
|
||||
}
|
||||
info[13] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="28"
|
||||
}
|
||||
info[14] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="-88"
|
||||
}
|
||||
info[15] {
|
||||
chan=""
|
||||
value=""
|
||||
connector="use"
|
||||
comparator="equals"
|
||||
clr="1"
|
||||
RISCpad="0"
|
||||
}
|
||||
fg_enable="on"
|
||||
bg_enable="on"
|
||||
default_fg="0"
|
||||
default_bg="1"
|
||||
}
|
||||
}
|
||||
"<<basic attribute>>" {
|
||||
attr {
|
||||
clr="0"
|
||||
style="solid"
|
||||
fill="outline"
|
||||
width="0"
|
||||
}
|
||||
}
|
||||
"text" {
|
||||
object {
|
||||
x="44"
|
||||
y="16"
|
||||
width="104"
|
||||
height="14"
|
||||
groupid="0"
|
||||
}
|
||||
textix="Sync"
|
||||
align="horiz. left"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text" {
|
||||
object {
|
||||
x="260"
|
||||
y="13"
|
||||
width="92"
|
||||
height="17"
|
||||
groupid="0"
|
||||
}
|
||||
textix="Async"
|
||||
align="horiz. left"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="15"
|
||||
y="88"
|
||||
width="170"
|
||||
height="22"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="fred"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="16"
|
||||
y="133"
|
||||
width="169"
|
||||
height="17"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="fred"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="15"
|
||||
y="43"
|
||||
width="168"
|
||||
height="26"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="fred"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="215"
|
||||
y="81"
|
||||
width="170"
|
||||
height="30"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="freddy"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="216"
|
||||
y="133"
|
||||
width="171"
|
||||
height="18"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="freddy"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="215"
|
||||
y="43"
|
||||
width="168"
|
||||
height="28"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="freddy"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="16"
|
||||
y="225"
|
||||
width="171"
|
||||
height="19"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="jane"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="17"
|
||||
y="259"
|
||||
width="170"
|
||||
height="20"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="jane"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="15"
|
||||
y="187"
|
||||
width="170"
|
||||
height="19"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="jane"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
"indicator" {
|
||||
object {
|
||||
x="219"
|
||||
y="218"
|
||||
width="173"
|
||||
height="23"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="janet"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
RISC_pad="0"
|
||||
}
|
||||
"text update" {
|
||||
object {
|
||||
x="220"
|
||||
y="257"
|
||||
width="174"
|
||||
height="20"
|
||||
groupid="0"
|
||||
}
|
||||
monitor {
|
||||
chan="janet"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="none"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="append"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
align="horiz. left"
|
||||
format="decimal"
|
||||
}
|
||||
"valuator" {
|
||||
object {
|
||||
x="219"
|
||||
y="188"
|
||||
width="171"
|
||||
height="21"
|
||||
groupid="0"
|
||||
}
|
||||
control {
|
||||
chan="janet"
|
||||
clr="0"
|
||||
bclr="1"
|
||||
label="limits"
|
||||
clrmod="static"
|
||||
rulechan[0] = ""
|
||||
rulechan[1] = ""
|
||||
rulechan[2] = ""
|
||||
rulechan[3] = ""
|
||||
rulechan[4] = ""
|
||||
rulechan[5] = ""
|
||||
rulechan[6] = ""
|
||||
rulechan[7] = ""
|
||||
rulechan[8] = ""
|
||||
rulechan[9] = ""
|
||||
rulechan[10] = ""
|
||||
rulechan[11] = ""
|
||||
rulechan[12] = ""
|
||||
rulechan[13] = ""
|
||||
rulechan[14] = ""
|
||||
rulechan[15] = ""
|
||||
clrrule="alarm"
|
||||
clrargs=""
|
||||
rulecolorbg="0"
|
||||
rulecolorfg="0"
|
||||
hdl="0"
|
||||
ldl="0"
|
||||
prec="-1"
|
||||
newunits=""
|
||||
units="none"
|
||||
decorate="none"
|
||||
convertFunc=""
|
||||
convertParams=""
|
||||
}
|
||||
direction="down"
|
||||
gain="coarse"
|
||||
sendMode="send on motion"
|
||||
increment="0"
|
||||
}
|
||||
81
src/cas/example/directoryService/vxEntry.cc
Normal file
81
src/cas/example/directoryService/vxEntry.cc
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// $Id$
|
||||
// Author: Jeff HIll (LANL)
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.2 1997/04/10 19:39:26 jhill
|
||||
// API changes
|
||||
//
|
||||
// Revision 1.1 1996/12/06 22:20:22 jhill
|
||||
// moved down one level
|
||||
//
|
||||
// Revision 1.2 1996/09/16 18:22:09 jhill
|
||||
// added cvs log entries
|
||||
//
|
||||
//
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// so we can call this from the vxWorks shell
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
exServer *pExampleCAS;
|
||||
|
||||
//
|
||||
// excas ()
|
||||
// (vxWorks example server entry point)
|
||||
//
|
||||
int excas (unsigned debugLevel, unsigned delaySec)
|
||||
{
|
||||
osiTime begin(osiTime::getCurrent());
|
||||
exServer *pCAS;
|
||||
|
||||
pCAS = new exServer(32u,5u,500u);
|
||||
if (!pCAS) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pCAS->setDebugLevel(debugLevel);
|
||||
pExampleCAS = pCAS;
|
||||
|
||||
if (delaySec==0u) {
|
||||
//
|
||||
// loop here forever
|
||||
//
|
||||
while (1) {
|
||||
taskDelay(10);
|
||||
}
|
||||
}
|
||||
else {
|
||||
osiTime total( ((float)delaySec) );
|
||||
osiTime delay(osiTime::getCurrent() - begin);
|
||||
//
|
||||
// loop here untill the specified execution time
|
||||
// expires
|
||||
//
|
||||
while (delay < total) {
|
||||
taskDelay(10);
|
||||
delay = osiTime::getCurrent() - begin;
|
||||
}
|
||||
}
|
||||
pCAS->show(debugLevel);
|
||||
pExampleCAS = NULL;
|
||||
delete pCAS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int excasShow(unsigned level)
|
||||
{
|
||||
if (pExampleCAS!=NULL) {
|
||||
pExampleCAS->show(level);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
9
src/cas/example/iocmonitor/Makefile
Normal file
9
src/cas/example/iocmonitor/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
# $Log$
|
||||
|
||||
TOP=../../../..
|
||||
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
include $(TOP)/config/RULES_ARCHS
|
||||
|
||||
23
src/cas/example/iocmonitor/Makefile.Host
Normal file
23
src/cas/example/iocmonitor/Makefile.Host
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
# $Log$
|
||||
|
||||
CAS = ../../..
|
||||
TOP = $(CAS)/../..
|
||||
|
||||
include $(TOP)/config/CONFIG_BASE
|
||||
|
||||
CXXCMPLR = STRICT
|
||||
|
||||
PROD_LIBS := cas ca gdd Com
|
||||
|
||||
SRCS += mon.cc monAdl.cc monNode.cc monServer.cc
|
||||
|
||||
PROD := iocMonitor
|
||||
|
||||
include $(TOP)/config/RULES.Host
|
||||
|
||||
clean::
|
||||
@$(RM) iocMonitor
|
||||
@$(RM) -rf Templates.DB
|
||||
@$(RM) core
|
||||
|
||||
343
src/cas/example/iocmonitor/mon.cc
Normal file
343
src/cas/example/iocmonitor/mon.cc
Normal file
@@ -0,0 +1,343 @@
|
||||
|
||||
// Author: Jim Kowalkowski
|
||||
// Date: 1/97
|
||||
//
|
||||
// $Id$
|
||||
// $Log$
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "caProto.h"
|
||||
|
||||
// use lower 11 bits of address as index
|
||||
|
||||
#define ADDR_MASK 0x000007ff
|
||||
#define ADDR_CHECK 10
|
||||
#define ADDR_WARNING 20
|
||||
#define ADDR_DEATH 40
|
||||
#define REPEATER_PORT 5065
|
||||
|
||||
typedef enum { nodeAlive=0, nodeUnknown, nodeDead } nodeState;
|
||||
|
||||
// ----------------------------- host node ------------------------------
|
||||
|
||||
class netNode
|
||||
{
|
||||
public:
|
||||
netNode(unsigned long a,const char* pre);
|
||||
~netNode(void);
|
||||
|
||||
void report(void);
|
||||
void ping(void);
|
||||
nodeState state(void);
|
||||
nodeState state(time_t);
|
||||
|
||||
unsigned long addr;
|
||||
time_t last_ping;
|
||||
const char* name;
|
||||
struct netNode* next;
|
||||
};
|
||||
|
||||
netNode::netNode(unsigned long a,const char* pre)
|
||||
{
|
||||
struct in_addr& in = (struct in_addr&)a;
|
||||
struct hostent* entry;
|
||||
char *n,*x;
|
||||
|
||||
addr=a;
|
||||
time(&last_ping);
|
||||
|
||||
if((entry=gethostbyaddr((char*)&a,sizeof(a),AF_INET))==NULL)
|
||||
n=inet_ntoa(in);
|
||||
else
|
||||
n=entry->h_name;
|
||||
|
||||
x=new char[strlen(n)+1+strlen(pre)];
|
||||
strcpy(x,pre);
|
||||
strcat(x,n);
|
||||
name=x;
|
||||
next=NULL;
|
||||
}
|
||||
|
||||
netNode::~netNode(void)
|
||||
{
|
||||
char* n = (char*)name;
|
||||
delete [] n;
|
||||
}
|
||||
|
||||
void netNode::ping(void)
|
||||
{
|
||||
time(&last_ping);
|
||||
}
|
||||
|
||||
nodeState netNode::state(void)
|
||||
{
|
||||
time_t t;
|
||||
time(&t);
|
||||
return state(t);
|
||||
}
|
||||
|
||||
nodeState netNode::state(time_t t)
|
||||
{
|
||||
nodeState s;
|
||||
time_t x;
|
||||
x=t-last_ping;
|
||||
if(x<ADDR_WARNING)
|
||||
s=nodeAlive;
|
||||
else if(x<ADDR_DEATH)
|
||||
s=nodeUnknown;
|
||||
else
|
||||
s=nodeDead;
|
||||
return s;
|
||||
}
|
||||
|
||||
void netNode::report(void)
|
||||
{
|
||||
switch(state())
|
||||
{
|
||||
case nodeDead: printf(" IOC %s Dead\n",name); break;
|
||||
case nodeAlive: printf(" IOC %s Alive\n",name); break;
|
||||
case nodeUnknown: printf(" IOC %s Unknown\n",name); break;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------- database ---------------------------
|
||||
|
||||
class addrDb
|
||||
{
|
||||
public:
|
||||
addrDb(const char* p);
|
||||
~addrDb(void);
|
||||
|
||||
void report(void);
|
||||
netNode* findNode(unsigned long addr);
|
||||
netNode* addNode(unsigned long addr);
|
||||
private:
|
||||
const char* prefix;
|
||||
netNode** db;
|
||||
};
|
||||
|
||||
addrDb::addrDb(const char* p)
|
||||
{
|
||||
int i;
|
||||
const char* x = p?p:"_";
|
||||
char* y;
|
||||
y=new char[strlen(x)+1];
|
||||
strcpy(y,x);
|
||||
prefix=y;
|
||||
db=new netNode*[ADDR_MASK];
|
||||
for(i=0;i<ADDR_MASK;i++) db[i]=NULL;
|
||||
}
|
||||
|
||||
addrDb::~addrDb(void)
|
||||
{
|
||||
int i;
|
||||
netNode *c,*p;
|
||||
for(i=0;i<ADDR_MASK;i++)
|
||||
{
|
||||
for(c=db[i];c;)
|
||||
{
|
||||
p=c->next;
|
||||
delete c;
|
||||
c=p;
|
||||
}
|
||||
}
|
||||
delete [] db;
|
||||
}
|
||||
|
||||
void addrDb::report(void)
|
||||
{
|
||||
int i;
|
||||
netNode* n;
|
||||
for(i=0;i<ADDR_MASK;i++)
|
||||
{
|
||||
for(n=db[i];n;n=n->next)
|
||||
n->report();
|
||||
}
|
||||
}
|
||||
|
||||
netNode* addrDb::findNode(unsigned long addr)
|
||||
{
|
||||
netNode* t;
|
||||
for(t=db[addr&ADDR_MASK];t && t->addr!=addr;t=t->next);
|
||||
return t;
|
||||
}
|
||||
|
||||
netNode* addrDb::addNode(unsigned long addr)
|
||||
{
|
||||
unsigned long i;
|
||||
netNode* t;
|
||||
if((t=findNode(addr))==NULL)
|
||||
{
|
||||
i=addr&ADDR_MASK;
|
||||
t=new netNode(addr,prefix);
|
||||
t->next=db[i];
|
||||
db[i]=t;
|
||||
}
|
||||
else
|
||||
t->ping();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
addrDb* db;
|
||||
|
||||
int main(int argc, char* argv[] )
|
||||
{
|
||||
caHdr msg;
|
||||
struct sockaddr_in tsin;
|
||||
struct sockaddr ssin;
|
||||
struct timeval tout;
|
||||
struct hostent* entry;
|
||||
fd_set fds;
|
||||
char* name;
|
||||
netNode* node;
|
||||
int soc,retry,done,rlen,len;
|
||||
unsigned short cmd;
|
||||
unsigned long* iaddr;
|
||||
time_t curr,last;
|
||||
|
||||
if(argc<2)
|
||||
{
|
||||
fprintf(stderr,"Must enter a prefix for PVs on command line\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
db=new addrDb(argv[1]);
|
||||
|
||||
tsin.sin_port=htons(0);
|
||||
tsin.sin_family=AF_INET;
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((soc=socket(AF_INET,SOCK_DGRAM,17))<0)
|
||||
{
|
||||
perror("open socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((bind(soc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("local bind failed to soc failed");
|
||||
close(soc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset((char*)&msg,0,sizeof(msg));
|
||||
msg.m_cmmd = htons(REPEATER_REGISTER);
|
||||
msg.m_available = tsin.sin_addr.s_addr;
|
||||
tsin.sin_port=htons(REPEATER_PORT);
|
||||
|
||||
for(done=0,retry=0;done==0 && retry<3;retry++)
|
||||
{
|
||||
if(sendto(soc,(char*)&msg,sizeof(msg),0,
|
||||
(struct sockaddr*)&tsin,sizeof(tsin))<0)
|
||||
{
|
||||
perror("sendto failed");
|
||||
close(soc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc,&fds);
|
||||
tout.tv_sec=0;
|
||||
tout.tv_usec=500000;
|
||||
|
||||
switch(select(FD_SETSIZE,&fds,NULL,NULL,&tout))
|
||||
{
|
||||
case -1: /* bad */
|
||||
perror("first select failed");
|
||||
return -1;
|
||||
case 0: /* timeout */
|
||||
break;
|
||||
default: /* data ready */
|
||||
done=1;
|
||||
}
|
||||
}
|
||||
|
||||
if(done==1)
|
||||
{
|
||||
rlen=0;
|
||||
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
|
||||
{
|
||||
perror("first recvfrom failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd=ntohs(msg.m_cmmd);
|
||||
|
||||
if(cmd==REPEATER_CONFIRM)
|
||||
printf("Connected to repeater\n");
|
||||
else
|
||||
{
|
||||
printf("Cannot connect to repeater (%d)\n",(int)cmd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Cannot connect to repeater\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---------------- ready ---------------- */
|
||||
last=0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc,&fds);
|
||||
tout.tv_sec=ADDR_CHECK;
|
||||
tout.tv_usec=0;
|
||||
|
||||
switch(select(FD_SETSIZE,&fds,NULL,NULL,&tout))
|
||||
{
|
||||
case -1: /* bad */
|
||||
perror("main select failed");
|
||||
case 0: /* timeout */
|
||||
// db->report();
|
||||
break;
|
||||
default: /* data ready */
|
||||
{
|
||||
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
|
||||
{
|
||||
perror("first recvfrom failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iaddr=(unsigned long*)&msg.m_available;
|
||||
node=db->addNode(*iaddr);
|
||||
|
||||
// cmd=ntohs(msg.m_cmmd);
|
||||
// if(cmd==CA_PROTO_RSRV_IS_UP)
|
||||
// {
|
||||
// printf("Alive\n");
|
||||
// }
|
||||
// else
|
||||
// printf("Unidentified Command from 0x%8.8x\n",*iaddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
time(&curr);
|
||||
if((curr-last)>=ADDR_CHECK)
|
||||
{
|
||||
db->report();
|
||||
last=curr;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
95
src/cas/example/iocmonitor/monAdl.cc
Normal file
95
src/cas/example/iocmonitor/monAdl.cc
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
// Author: Jim Kowalkowski
|
||||
// Date: 1/97
|
||||
//
|
||||
// $Id$
|
||||
// $Log$
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "monNode.h"
|
||||
#include "monServer.h"
|
||||
|
||||
#define WIDTH 180
|
||||
#define HEIGHT 10
|
||||
#define MAX_WIDTH 1000
|
||||
#define MAX_HEIGHT 700
|
||||
#define TOTAL_X (MAX_WIDTH/WIDTH)
|
||||
#define TOTAL_Y (MAX_HEIGHT/HEIGHT)
|
||||
|
||||
int monAdl(monNode** head, char* fname,const char* prefix)
|
||||
{
|
||||
FILE *fdout;
|
||||
int dh;
|
||||
int i,j,k;
|
||||
monNode* node;
|
||||
|
||||
if((fdout=fopen(fname,"w"))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Cannot open the ADL file %s\n",fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dh=monNode::total/TOTAL_X;
|
||||
if((dh*TOTAL_X)!=monNode::total) ++dh;
|
||||
|
||||
fprintf(fdout,"\nfile { name=\"ioc_status.adl\" version=020209 }\n");
|
||||
fprintf(fdout,"display {\n");
|
||||
fprintf(fdout," object { x=0 y=0 width=%d height=%d }\n",
|
||||
MAX_WIDTH,dh*HEIGHT+40);
|
||||
fprintf(fdout," clr=37 bclr=14 cmap=\"\"\n}\n");
|
||||
|
||||
fprintf(fdout,"\"color map\" { ncolors=65 colors {\n");
|
||||
fprintf(fdout,"ffffff, ececec, dadada, c8c8c8, bbbbbb, aeaeae, 9e9e9e,\n");
|
||||
fprintf(fdout,"919191, 858585, 787878, 696969, 5a5a5a, 464646, 2d2d2d,\n");
|
||||
fprintf(fdout,"000000, 00d800, 1ebb00, 339900, 2d7f00, 216c00, fd0000,\n");
|
||||
fprintf(fdout,"de1309, be190b, a01207, 820400, 5893ff, 597ee1, 4b6ec7,\n");
|
||||
fprintf(fdout,"3a5eab, 27548d, fbf34a, f9da3c, eeb62b, e19015, cd6100,\n");
|
||||
fprintf(fdout,"ffb0ff, d67fe2, ae4ebc, 8b1a96, 610a75, a4aaff, 8793e2,\n");
|
||||
fprintf(fdout,"6a73c1, 4d52a4, 343386, c7bb6d, b79d5c, a47e3c, 7d5627,\n");
|
||||
fprintf(fdout,"58340f, 99ffff, 73dfff, 4ea5f9, 2a63e4, 0a00b8, ebf1b5,\n");
|
||||
fprintf(fdout,"d4db9d, bbc187, a6a462, 8b8239, 73ff6b, 52da3b, 3cb420,\n");
|
||||
fprintf(fdout,"289315, 1a7309,\n");
|
||||
fprintf(fdout,"} }\n");
|
||||
|
||||
// ----------------------- heading ----------------------------------
|
||||
i=(MAX_WIDTH/2)-(300/2);
|
||||
fprintf(fdout," text { object { x=%d y=2 width=300 height=25 }\n",i);
|
||||
fprintf(fdout," \"basic attribute\" { clr=37 }\n");
|
||||
fprintf(fdout," textix=\"%d IOC STATUS MONITOR\"\n",monNode::total);
|
||||
fprintf(fdout," align=\"horiz. centered\"\n}\n");
|
||||
|
||||
// ---------------------- generate new file button -------------------
|
||||
fprintf(fdout,"\"message button\" { object\n");
|
||||
fprintf(fdout," { x=%d y=2 width=180 height=22 }\n",MAX_WIDTH-180);
|
||||
fprintf(fdout," control { chan=\"%smakeScreen\" clr=31 bclr=47 }\n",prefix);
|
||||
fprintf(fdout," label=\"Make New Screen\" press_msg=\"1\"\n}\n");
|
||||
|
||||
fprintf(fdout,"\"text update\" { object { x=1 y=2 width=180 height=22 }\n");
|
||||
fprintf(fdout," monitor { chan=\"%siocCount\" clr=31 bclr=14 }\n",prefix);
|
||||
fprintf(fdout,"}\n");
|
||||
|
||||
// -------------- make all the buttons
|
||||
i=0;j=0;
|
||||
for(k=0;k<ADDR_TOTAL;k++)
|
||||
{
|
||||
for(node=head[k];node;node=node->next)
|
||||
{
|
||||
fprintf(fdout,"\"text update\" {\n");
|
||||
fprintf(fdout," object { x=%d y=%d width=%d height=%d }\n",
|
||||
i*WIDTH,j*HEIGHT+30,WIDTH,HEIGHT);
|
||||
|
||||
if(++i>=TOTAL_X) { i=0; ++j; }
|
||||
|
||||
fprintf(fdout," monitor { chan=\"%s\" clr=0 bclr=14 }\n",
|
||||
node->name);
|
||||
fprintf(fdout," clrmod=\"alarm\"\n}\n");
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
283
src/cas/example/iocmonitor/monNode.cc
Normal file
283
src/cas/example/iocmonitor/monNode.cc
Normal file
@@ -0,0 +1,283 @@
|
||||
|
||||
// Author: Jim Kowalkowski
|
||||
// Date: 1/97
|
||||
//
|
||||
// $Id$
|
||||
// $Log$
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "gddAppTable.h"
|
||||
#include "monServer.h"
|
||||
#include "monNode.h"
|
||||
|
||||
// --------------------------- monPv ----------------------------
|
||||
|
||||
monPv::monPv(const casCtx& c,monServer& s,monNode* n,const char* name):
|
||||
casPV(c,name),node(n),mrg(s)
|
||||
{
|
||||
monDebug1(5,"monPV: Creating PV for %s\n",name);
|
||||
data=NULL;
|
||||
markNotInterested();
|
||||
node->setPv(this);
|
||||
}
|
||||
|
||||
monPv::~monPv(void)
|
||||
{
|
||||
node->clearPv();
|
||||
if(data) data->unreference();
|
||||
monDebug1(5,"monPV: Deleting PV for %s\n",node->name);
|
||||
}
|
||||
|
||||
unsigned monPv::maxSimultAsyncOps(void) const { return 5000u; }
|
||||
void monPv::interestDelete(void) { markNotInterested(); }
|
||||
aitEnum monPv::bestExternalType(void) const { return aitEnumString; }
|
||||
unsigned monPv::maxDimension(void) const { return 0; }
|
||||
aitIndex monPv::maxBound(unsigned dim) const { return 0; }
|
||||
void monPv::destroy(void) { casPV::destroy(); }
|
||||
|
||||
caStatus monPv::interestRegister(void)
|
||||
{
|
||||
markInterested();
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
caStatus monPv::read(const casCtx& ctx, gdd& dd)
|
||||
{
|
||||
monDebug1(5,"monPV: Read PV data=0x%8.8x\n",(int)data);
|
||||
gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable();
|
||||
if(data) table.smartCopy(&dd,data);
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
caStatus monPv::write(const casCtx& /*ctx*/, gdd& /*dd*/)
|
||||
{
|
||||
// cannot write to these PVs
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
void monPv::eventData(void)
|
||||
{
|
||||
struct tm* t;
|
||||
char val[40];
|
||||
char str[10];
|
||||
aitTimeStamp stamp(node->state_ping,0);
|
||||
|
||||
// prepare a new gdd used for posting and reads
|
||||
if(data) data->unreference();
|
||||
data=new gddScalar(mrg.appValue,aitEnumString);
|
||||
t=localtime(&node->state_ping);
|
||||
|
||||
switch(node->state())
|
||||
{
|
||||
case monAlive:
|
||||
strcpy(str,"Up");
|
||||
data->setStatSevr(0,NO_ALARM);
|
||||
break;
|
||||
case monUnknown:
|
||||
strcpy(str,"?");
|
||||
data->setStatSevr(TIMEOUT_ALARM,MINOR_ALARM);
|
||||
break;
|
||||
case monDead:
|
||||
strcpy(str,"Down");
|
||||
data->setStatSevr(COMM_ALARM,MAJOR_ALARM);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
sprintf(val,"(%s %s %2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d)",
|
||||
&node->name[mrg.prefix_length],str,
|
||||
t->tm_mon+1,t->tm_mday,t->tm_year,t->tm_hour,t->tm_min,t->tm_sec);
|
||||
*/
|
||||
sprintf(val,"(%2.2d/%2.2d %2.2d:%2.2d:%2.2d %s)",
|
||||
t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec,
|
||||
&node->name[mrg.prefix_length]);
|
||||
|
||||
data->reference();
|
||||
data->setTimeStamp(&stamp);
|
||||
data->put(val);
|
||||
|
||||
monDebug1(5,"monPV: eventData data=0x%8.8x\n",(int)data);
|
||||
if(debugLevel>6) data->dump();
|
||||
|
||||
if(isMonitored())
|
||||
{
|
||||
monDebug0(5,"monPV: PV monitored\n");
|
||||
casEventMask select(
|
||||
mrg.alarmEventMask|mrg.valueEventMask|mrg.logEventMask);
|
||||
postEvent(select,*data);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------- monNode ----------------------------
|
||||
|
||||
monNode::monNode(unsigned long a,const char* prefix)
|
||||
{
|
||||
struct in_addr& in = (struct in_addr&)a;
|
||||
struct hostent* entry;
|
||||
char *n,*x;
|
||||
|
||||
addr=a;
|
||||
time(&last_ping);
|
||||
state_ping=last_ping;
|
||||
|
||||
if((entry=gethostbyaddr((char*)&a,sizeof(a),AF_INET))==NULL)
|
||||
n=inet_ntoa(in);
|
||||
else
|
||||
n=entry->h_name;
|
||||
|
||||
x=new char[strlen(n)+1+strlen(prefix)];
|
||||
strcpy(x,prefix);
|
||||
strcat(x,n);
|
||||
name=x;
|
||||
next=NULL;
|
||||
pv=NULL;
|
||||
last_state=monAlive;
|
||||
++monNode::total;
|
||||
monDebug1(5,"monNode: Created node %s\n",name);
|
||||
}
|
||||
|
||||
monNode::~monNode(void)
|
||||
{
|
||||
monDebug1(5,"monNode: Deleted node %s\n",name);
|
||||
char* n = (char*)name;
|
||||
delete [] n;
|
||||
}
|
||||
|
||||
int monNode::total=0;
|
||||
|
||||
void monNode::ping(void)
|
||||
{
|
||||
time(&last_ping);
|
||||
}
|
||||
|
||||
monState monNode::state(void)
|
||||
{
|
||||
return last_state;
|
||||
}
|
||||
|
||||
monState monNode::state(time_t t)
|
||||
{
|
||||
monState s;
|
||||
time_t x;
|
||||
x=t-last_ping;
|
||||
if(x<ADDR_WARNING)
|
||||
s=monAlive;
|
||||
else if(x<ADDR_DEATH)
|
||||
s=monUnknown;
|
||||
else
|
||||
s=monDead;
|
||||
return s;
|
||||
}
|
||||
|
||||
void monNode::check(time_t t)
|
||||
{
|
||||
monState s = state(t);
|
||||
monDebug1(9,"monNode: Checking node %s\n",name);
|
||||
|
||||
if(s!=last_state)
|
||||
{
|
||||
last_state=s;
|
||||
// only change boot time if going from/to dead
|
||||
if(s==monDead || last_state==monDead) state_ping=t;
|
||||
if(pv) pv->eventData();
|
||||
}
|
||||
}
|
||||
|
||||
void monNode::setPv(monPv* p)
|
||||
{
|
||||
int need;
|
||||
monDebug1(9,"monNode: Setting PV for %s\n",name);
|
||||
|
||||
if(pv==NULL)
|
||||
need=1;
|
||||
else
|
||||
need=0;
|
||||
|
||||
pv=p;
|
||||
if(need) pv->eventData();
|
||||
}
|
||||
|
||||
void monNode::clearPv(void) { pv=NULL; }
|
||||
|
||||
void monNode::report(FILE* fd)
|
||||
{
|
||||
struct in_addr* ia = (struct in_addr*)&addr;
|
||||
switch(state())
|
||||
{
|
||||
case monDead:
|
||||
fprintf(fd,"%s %s Dead\n",name,inet_ntoa(*ia));
|
||||
break;
|
||||
case monAlive:
|
||||
fprintf(fd,"%s %s Alive\n",name,inet_ntoa(*ia));
|
||||
break;
|
||||
case monUnknown:
|
||||
fprintf(fd,"%s %s Unknown\n",name,inet_ntoa(*ia));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------- status PVs -----------------------
|
||||
|
||||
makeScreenPV::~makeScreenPV(void) { }
|
||||
aitEnum makeScreenPV::bestExternalType(void) const { return aitEnumInt32; }
|
||||
|
||||
caStatus makeScreenPV::read(const casCtx& /*ctx*/, gdd& /*dd*/)
|
||||
{
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
caStatus makeScreenPV::write(const casCtx& /*ctx*/, gdd& /*dd*/)
|
||||
{
|
||||
mrg.makeADL();
|
||||
return S_casApp_success; // cannot write to these PVs
|
||||
}
|
||||
|
||||
// -------------
|
||||
|
||||
iocCountPV::~iocCountPV(void) { mrg.count_pv=NULL; }
|
||||
void iocCountPV::interestDelete(void) { monitored=0; }
|
||||
|
||||
aitEnum iocCountPV::bestExternalType(void) const { return aitEnumInt32; }
|
||||
|
||||
void iocCountPV::postValue(void)
|
||||
{
|
||||
gdd* value=new gddScalar(mrg.appValue,aitEnumInt32);
|
||||
value->put(monNode::total);
|
||||
|
||||
if(monitored)
|
||||
{
|
||||
casEventMask select(
|
||||
mrg.alarmEventMask|mrg.valueEventMask|mrg.logEventMask);
|
||||
postEvent(select,*value);
|
||||
}
|
||||
}
|
||||
|
||||
caStatus iocCountPV::interestRegister(void)
|
||||
{
|
||||
monitored=1;
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
|
||||
caStatus iocCountPV::read(const casCtx& ctx, gdd& dd)
|
||||
{
|
||||
// this is bad, should check for dd to be scalar, if it is not a scalar,
|
||||
// then find the value gdd within the container
|
||||
dd.put(monNode::total);
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
caStatus iocCountPV::write(const casCtx& /*ctx*/, gdd& /*dd*/)
|
||||
{
|
||||
return S_casApp_success; // cannot write to these PVs
|
||||
}
|
||||
|
||||
118
src/cas/example/iocmonitor/monNode.h
Normal file
118
src/cas/example/iocmonitor/monNode.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef MONNODE_H
|
||||
#define MONNODE_H
|
||||
|
||||
/*
|
||||
* Author: Jim Kowalkowski
|
||||
* Date: 1/97
|
||||
*
|
||||
* $Id$
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "aitTypes.h"
|
||||
#include "casdef.h"
|
||||
|
||||
typedef enum { monAlive=0, monUnknown, monDead } monState;
|
||||
|
||||
#define ADDR_CHECK 10
|
||||
#define ADDR_WARNING 20
|
||||
#define ADDR_DEATH 40
|
||||
|
||||
class monNode;
|
||||
class monServer;
|
||||
class gdd;
|
||||
|
||||
class monPv : public casPV
|
||||
{
|
||||
public:
|
||||
monPv(const casCtx&,monServer&,monNode*,const char* pv_name);
|
||||
virtual ~monPv(void);
|
||||
|
||||
// CA server interface functions
|
||||
virtual caStatus interestRegister(void);
|
||||
virtual void interestDelete(void);
|
||||
virtual aitEnum bestExternalType(void) const;
|
||||
virtual caStatus read(const casCtx &ctx, gdd &prototype);
|
||||
virtual caStatus write(const casCtx &ctx, gdd &value);
|
||||
virtual void destroy(void);
|
||||
virtual unsigned maxSimultAsyncOps(void) const;
|
||||
virtual unsigned maxDimension(void) const;
|
||||
virtual aitIndex maxBound(unsigned dim) const;
|
||||
|
||||
void eventData(void);
|
||||
|
||||
void markInterested(void) { monitor=1; }
|
||||
void markNotInterested(void) { monitor=0; }
|
||||
int isMonitored(void) { return monitor; }
|
||||
|
||||
monServer& mrg;
|
||||
monNode* node;
|
||||
int monitor;
|
||||
gdd* data;
|
||||
};
|
||||
|
||||
class monNode
|
||||
{
|
||||
public:
|
||||
monNode(unsigned long a, const char* prefix);
|
||||
~monNode(void);
|
||||
|
||||
void report(FILE*);
|
||||
void ping(void);
|
||||
void check(time_t);
|
||||
monState state(void);
|
||||
monState state(time_t);
|
||||
void setPv(monPv*);
|
||||
void clearPv(void);
|
||||
|
||||
unsigned long addr;
|
||||
time_t last_ping;
|
||||
time_t state_ping;
|
||||
const char* name;
|
||||
monPv* pv;
|
||||
monNode* next;
|
||||
monState last_state;
|
||||
static int total;
|
||||
};
|
||||
|
||||
// ---------------------------- status PVs --------------------------
|
||||
|
||||
class makeScreenPV : public casPV
|
||||
{
|
||||
public:
|
||||
makeScreenPV(const casCtx& c,const char* pv_name,monServer& s):
|
||||
casPV(c,pv_name),mrg(s){}
|
||||
virtual ~makeScreenPV(void);
|
||||
|
||||
// CA server interface functions
|
||||
virtual aitEnum bestExternalType(void) const;
|
||||
virtual caStatus read(const casCtx &ctx, gdd &prototype);
|
||||
virtual caStatus write(const casCtx &ctx, gdd &value);
|
||||
|
||||
monServer& mrg;
|
||||
};
|
||||
|
||||
class iocCountPV : public casPV
|
||||
{
|
||||
public:
|
||||
iocCountPV(const casCtx& c,const char* pv_name,monServer& s):
|
||||
casPV(c,pv_name),mrg(s),monitored(0) {}
|
||||
virtual ~iocCountPV(void);
|
||||
|
||||
// CA server interface functions
|
||||
virtual caStatus interestRegister(void);
|
||||
virtual void interestDelete(void);
|
||||
virtual aitEnum bestExternalType(void) const;
|
||||
virtual caStatus read(const casCtx &ctx, gdd &prototype);
|
||||
virtual caStatus write(const casCtx &ctx, gdd &value);
|
||||
|
||||
void postValue(void);
|
||||
|
||||
int monitored;
|
||||
monServer& mrg;
|
||||
};
|
||||
|
||||
#endif
|
||||
358
src/cas/example/iocmonitor/monServer.cc
Normal file
358
src/cas/example/iocmonitor/monServer.cc
Normal file
@@ -0,0 +1,358 @@
|
||||
|
||||
// Author: Jim Kowalkowski
|
||||
// Date: 1/97
|
||||
//
|
||||
// $Id$
|
||||
// $Log$
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "caProto.h"
|
||||
#include "gddAppTable.h"
|
||||
|
||||
#include "monServer.h"
|
||||
#include "monNode.h"
|
||||
|
||||
int debugLevel=0;
|
||||
int makeReport=0;
|
||||
int keepGoing=1;
|
||||
|
||||
typedef void (*SIG_FUNC)(int);
|
||||
|
||||
static SIG_FUNC save_hup = NULL;
|
||||
static SIG_FUNC save_int = NULL;
|
||||
static SIG_FUNC save_term = NULL;
|
||||
static SIG_FUNC save_usr1 = NULL;
|
||||
|
||||
static void sig_end(int)
|
||||
{
|
||||
signal(SIGHUP,sig_end);
|
||||
signal(SIGTERM,sig_end);
|
||||
signal(SIGINT,sig_end);
|
||||
keepGoing=0;
|
||||
}
|
||||
static void sig_usr1(int) { makeReport=1; signal(SIGUSR1,sig_usr1); }
|
||||
|
||||
extern int monAdl(monNode**,char*,const char*);
|
||||
|
||||
// ------------------------- file descriptor servicing ----------------------
|
||||
|
||||
monFd::~monFd(void) { }
|
||||
void monFd::callBack(void) { server.dataReady(); }
|
||||
|
||||
// -------------------------- server -----------------------------
|
||||
|
||||
monServer::monServer(unsigned namelen,unsigned pvcount,unsigned simio,
|
||||
const char* p):caServer(namelen,pvcount,simio)
|
||||
{
|
||||
int i;
|
||||
count_pv=NULL;
|
||||
const char* x = p?p:"_";
|
||||
prefix=new char[strlen(x)+1];
|
||||
strcpy(prefix,x);
|
||||
prefix_length=strlen(prefix);
|
||||
soc_fd=NULL;
|
||||
db=new monNode*[ADDR_TOTAL];
|
||||
for(i=0;i<ADDR_TOTAL;i++) db[i]=NULL;
|
||||
|
||||
gddApplicationTypeTable& tt = gddApplicationTypeTable::AppTable();
|
||||
appValue=tt.getApplicationType("value");
|
||||
|
||||
sprintf(ioc_count_name,"%siocCount",prefix);
|
||||
sprintf(make_screen_name,"%smakeScreen",prefix);
|
||||
}
|
||||
|
||||
monServer::~monServer(void)
|
||||
{
|
||||
int i;
|
||||
monNode *c,*p;
|
||||
for(i=0;i<ADDR_TOTAL;i++)
|
||||
{
|
||||
for(c=db[i];c;)
|
||||
{
|
||||
p=c->next;
|
||||
delete c;
|
||||
c=p;
|
||||
}
|
||||
}
|
||||
delete [] db;
|
||||
}
|
||||
|
||||
void monServer::report(FILE* fd)
|
||||
{
|
||||
int i;
|
||||
monNode* n;
|
||||
for(i=0;i<ADDR_TOTAL;i++)
|
||||
{
|
||||
for(n=db[i];n;n=n->next)
|
||||
n->report(fd);
|
||||
}
|
||||
}
|
||||
|
||||
monNode* monServer::findNode(unsigned long addr)
|
||||
{
|
||||
monNode* t;
|
||||
for(t=db[addr&ADDR_MASK];t && t->addr!=addr;t=t->next);
|
||||
return t;
|
||||
}
|
||||
|
||||
monNode* monServer::addNode(unsigned long addr)
|
||||
{
|
||||
unsigned long i;
|
||||
monNode* t;
|
||||
if((t=findNode(addr))==NULL)
|
||||
{
|
||||
i=addr&ADDR_MASK;
|
||||
t=new monNode(addr,prefix);
|
||||
t->next=db[i];
|
||||
db[i]=t;
|
||||
pv_list.add(t->name,*t);
|
||||
if(count_pv) count_pv->postValue();
|
||||
}
|
||||
else
|
||||
t->ping();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void monServer::checkEvent(void)
|
||||
{
|
||||
// go through all the nodes and send out monitors on PV if required
|
||||
time_t t;
|
||||
int i;
|
||||
monNode* n;
|
||||
time(&t);
|
||||
|
||||
for(i=0;i<ADDR_TOTAL;i++)
|
||||
{
|
||||
for(n=db[i];n;n=n->next)
|
||||
n->check(t);
|
||||
}
|
||||
}
|
||||
|
||||
pvExistReturn monServer::pvExistTest(const casCtx& c,const char* pvname)
|
||||
{
|
||||
monNode* node;
|
||||
|
||||
if(strcmp(pvname,ioc_count_name)==0)
|
||||
return pvExistReturn(S_casApp_success,ioc_count_name);
|
||||
|
||||
if(strcmp(pvname,make_screen_name)==0)
|
||||
return pvExistReturn(S_casApp_success,make_screen_name);
|
||||
|
||||
if(pv_list.find(pvname,node)==0)
|
||||
return pvExistReturn(S_casApp_success,node->name);
|
||||
else
|
||||
return pvExistReturn(S_casApp_pvNotFound);
|
||||
}
|
||||
|
||||
casPV* monServer::createPV(const casCtx& c,const char* pvname)
|
||||
{
|
||||
monNode* node;
|
||||
|
||||
if(strcmp(pvname,ioc_count_name)==0)
|
||||
return count_pv=new iocCountPV(c,pvname,*this);
|
||||
|
||||
if(strcmp(pvname,make_screen_name)==0)
|
||||
return new makeScreenPV(c,pvname,*this);
|
||||
|
||||
if(pv_list.find(pvname,node)==0)
|
||||
return new monPv(c,*this,node,pvname);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int monServer::repeaterConnect(void)
|
||||
{
|
||||
caHdr msg;
|
||||
struct sockaddr_in tsin;
|
||||
struct sockaddr ssin;
|
||||
struct timeval tout;
|
||||
fd_set fds;
|
||||
int retry,done,rlen,len;
|
||||
|
||||
tsin.sin_port=htons(0);
|
||||
tsin.sin_family=AF_INET;
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((soc=socket(AF_INET,SOCK_DGRAM,17))<0)
|
||||
{
|
||||
perror("open socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((bind(soc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("local bind failed to soc failed");
|
||||
close(soc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset((char*)&msg,0,sizeof(msg));
|
||||
msg.m_cmmd = htons(REPEATER_REGISTER);
|
||||
msg.m_available = tsin.sin_addr.s_addr;
|
||||
tsin.sin_port=htons(REPEATER_PORT);
|
||||
|
||||
for(done=0,retry=0;done==0 && retry<3;retry++)
|
||||
{
|
||||
if(sendto(soc,(char*)&msg,sizeof(msg),0,
|
||||
(struct sockaddr*)&tsin,sizeof(tsin))<0)
|
||||
{
|
||||
perror("sendto failed");
|
||||
close(soc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc,&fds);
|
||||
tout.tv_sec=0;
|
||||
tout.tv_usec=500000;
|
||||
|
||||
switch(select(FD_SETSIZE,&fds,NULL,NULL,&tout))
|
||||
{
|
||||
case -1: /* bad */
|
||||
perror("first select failed");
|
||||
return -1;
|
||||
case 0: /* timeout */
|
||||
break;
|
||||
default: /* data ready */
|
||||
done=1;
|
||||
}
|
||||
}
|
||||
|
||||
if(done==1)
|
||||
{
|
||||
rlen=0;
|
||||
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
|
||||
{
|
||||
perror("first recvfrom failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ntohs(msg.m_cmmd)==REPEATER_CONFIRM)
|
||||
printf("Connected to repeater\n");
|
||||
else
|
||||
{
|
||||
printf("Cannot connect to repeater (%d)\n",(int)ntohs(msg.m_cmmd));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Cannot connect to repeater\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
soc_fd=new monFd(soc,fdrRead,*this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void monServer::dataReady(void)
|
||||
{
|
||||
caHdr msg;
|
||||
struct sockaddr ssin;
|
||||
monNode* node;
|
||||
int rlen,len;
|
||||
unsigned long* iaddr;
|
||||
|
||||
rlen=0;
|
||||
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
|
||||
{
|
||||
perror("first recvfrom failed");
|
||||
}
|
||||
else if(ntohs(msg.m_cmmd)==CA_PROTO_RSRV_IS_UP)
|
||||
{
|
||||
iaddr=(unsigned long*)&msg.m_available;
|
||||
node=addNode(*iaddr);
|
||||
}
|
||||
}
|
||||
|
||||
void monServer::mainLoop(void)
|
||||
{
|
||||
osiTime delay(ADDR_CHECK,0u);
|
||||
time_t curr,prev;
|
||||
|
||||
if(repeaterConnect()<0) return;
|
||||
|
||||
prev=0;
|
||||
while(keepGoing)
|
||||
{
|
||||
fileDescriptorManager.process(delay);
|
||||
time(&curr);
|
||||
if((curr-prev)>=ADDR_CHECK)
|
||||
{
|
||||
checkEvent();
|
||||
prev=curr;
|
||||
}
|
||||
|
||||
if(makeReport)
|
||||
{
|
||||
FILE* fd;
|
||||
if((fd=fopen("PV_REPORT","w")))
|
||||
{
|
||||
report(fd);
|
||||
fclose(fd);
|
||||
}
|
||||
makeADL();
|
||||
makeReport=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void monServer::makeADL(void) { monAdl(db,"ioc_status.adl",prefix); }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if(argc<2)
|
||||
{
|
||||
fprintf(stderr,"Must enter a prefix for PVs on command line\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(argc==3) sscanf(argv[2],"%d",&debugLevel);
|
||||
|
||||
// disassociate from parent
|
||||
switch(fork())
|
||||
{
|
||||
case -1: // error
|
||||
perror("Cannot create gateway processes");
|
||||
return -1;
|
||||
case 0: // child
|
||||
#if defined linux || defined SOLARIS
|
||||
setpgrp();
|
||||
#else
|
||||
setpgrp(0,0);
|
||||
#endif
|
||||
setsid();
|
||||
break;
|
||||
default: // parent
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
save_hup=signal(SIGHUP,sig_end);
|
||||
save_term=signal(SIGTERM,sig_end);
|
||||
save_int=signal(SIGINT,sig_end);
|
||||
save_usr1=signal(SIGUSR1,sig_usr1);
|
||||
|
||||
monServer* ms = new monServer(32u,5u,2000u,argv[1]);
|
||||
ms->mainLoop();
|
||||
delete ms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
94
src/cas/example/iocmonitor/monServer.h
Normal file
94
src/cas/example/iocmonitor/monServer.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef MONSERVER_H
|
||||
#define MONSERVER_H
|
||||
|
||||
/*
|
||||
* Author: Jim Kowalkowski
|
||||
* Date: 1/97
|
||||
*
|
||||
* $Id$
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
#include "casdef.h"
|
||||
#include "tsHash.h"
|
||||
#include "fdManager.h"
|
||||
|
||||
#include "monNode.h"
|
||||
|
||||
class gdd;
|
||||
class monServer;
|
||||
|
||||
// use lower 11 bits of address as index
|
||||
#define ADDR_MASK 0x0000001f
|
||||
#define ADDR_TOTAL (ADDR_MASK+1)
|
||||
#define REPEATER_PORT 5065
|
||||
|
||||
// ---------------------- fd manager ------------------------
|
||||
|
||||
class monFd : public fdReg
|
||||
{
|
||||
public:
|
||||
monFd(const int fdIn,const fdRegType typ,monServer& s):
|
||||
fdReg(fdIn,typ),server(s) { }
|
||||
virtual ~monFd(void);
|
||||
private:
|
||||
virtual void callBack(void);
|
||||
monServer& server;
|
||||
};
|
||||
|
||||
// ---------------------------- server -------------------------------
|
||||
|
||||
class monServer : public caServer
|
||||
{
|
||||
public:
|
||||
monServer(unsigned max_name_len,unsigned pv_count_est,unsigned max_sim_io,
|
||||
const char* pre);
|
||||
virtual ~monServer(void);
|
||||
|
||||
// CAS virtual overloads
|
||||
virtual pvExistReturn pvExistTest(const casCtx& c,const char* pvname);
|
||||
virtual casPV* createPV(const casCtx& c,const char* pvname);
|
||||
|
||||
// CAS application management functions
|
||||
int repeaterConnect(void);
|
||||
void checkEvent(void);
|
||||
void dataReady(void);
|
||||
void mainLoop(void);
|
||||
void report(FILE*);
|
||||
void makeADL(void);
|
||||
|
||||
monNode* findNode(unsigned long addr);
|
||||
monNode* addNode(unsigned long addr);
|
||||
|
||||
int appValue;
|
||||
char* prefix;
|
||||
int prefix_length;
|
||||
iocCountPV* count_pv;
|
||||
private:
|
||||
tsHash<monNode> pv_list; // client pv list
|
||||
monNode** db;
|
||||
monFd* soc_fd;
|
||||
int soc;
|
||||
char ioc_count_name[40];
|
||||
char make_screen_name[40];
|
||||
};
|
||||
|
||||
extern int debugLevel;
|
||||
|
||||
/* debug macro creation */
|
||||
#ifdef NODEBUG
|
||||
#define monDebug(l,f,v) ;
|
||||
#else
|
||||
#define monDebug(l,f,v) { if(l<=debugLevel) \
|
||||
{ fprintf(stderr,f,v); fflush(stderr); }}
|
||||
#define monDebug0(l,f) { if(l<=debugLevel) \
|
||||
{ fprintf(stderr,f); fflush(stderr); } }
|
||||
#define monDebug1(l,f,v) { if(l<=debugLevel) \
|
||||
{ fprintf(stderr,f,v); fflush(stderr); }}
|
||||
#define monDebug2(l,f,v1,v2) { if(l<=debugLevel) \
|
||||
{ fprintf(stderr,f,v1,v2); fflush(stderr); }}
|
||||
#define monDebug3(l,f,v1,v2,v3) { if(l<=debugLevel) \
|
||||
{ fprintf(stderr,f,v1,v2,v3); fflush(stderr); }}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
115
src/cas/example/iocmonitor/tsDLHashList.h
Normal file
115
src/cas/example/iocmonitor/tsDLHashList.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#ifndef tsDLHashList_H
|
||||
#define tsDLHashList_H
|
||||
|
||||
/*
|
||||
* Author: Jim Kowalkowski
|
||||
* Date: 1/97
|
||||
*
|
||||
* $Id$
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "gpHash.h"
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class tsHash
|
||||
{
|
||||
private:
|
||||
void* hash_table;
|
||||
|
||||
public:
|
||||
gpHash(void)
|
||||
{
|
||||
hash_table=NULL;
|
||||
gphInitPvt(&hash_table);
|
||||
}
|
||||
|
||||
~gateHash(void) { gphFreeMem(hash_table); }
|
||||
|
||||
int add(const char* key, T& item);
|
||||
{
|
||||
GPHENTRY* entry;
|
||||
int rc;
|
||||
|
||||
entry=gphAdd(hash_table,(char*)key,hash_table);
|
||||
|
||||
if(entry==(GPHENTRY*)NULL)
|
||||
rc=-1;
|
||||
else
|
||||
{
|
||||
entry->userPvt=(void*)&item;
|
||||
rc=0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int remove(const char* key,T*& item);
|
||||
{
|
||||
int rc;
|
||||
|
||||
if(find(key,item)<0)
|
||||
rc=-1;
|
||||
else
|
||||
{
|
||||
gphDelete(hash_table,(char*)key,hash_table);
|
||||
rc=0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int find(const char* key, T*& item);
|
||||
{
|
||||
GPHENTRY* entry;
|
||||
int rc;
|
||||
|
||||
entry=gphFind(hash_table,(char*)key,hash_table);
|
||||
|
||||
if(entry==(GPHENTRY*)NULL)
|
||||
rc=-1;
|
||||
else
|
||||
{
|
||||
item=(T*)entry->userPvt;
|
||||
rc=0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class tsDLHashList : public tsDLList<T>
|
||||
{
|
||||
private:
|
||||
tsHash<T> h;
|
||||
public:
|
||||
int add(const char* key, T& item)
|
||||
{
|
||||
int rc;
|
||||
rc=h.add(key,item);
|
||||
add(item);
|
||||
return rc;
|
||||
}
|
||||
int find(const char* key, T*& item);
|
||||
{
|
||||
int rc=0;
|
||||
if(h.find(key,item)!=0)
|
||||
rc=-1;
|
||||
return rc;
|
||||
}
|
||||
int remove(const char* key,T*& item);
|
||||
{
|
||||
int rc=0;
|
||||
if(h.find(key,item)==0)
|
||||
{
|
||||
h.remove(key,item);
|
||||
remove(*item);
|
||||
}
|
||||
else
|
||||
rc=-1;
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
136
src/cas/example/iocmonitor/tsHash.h
Normal file
136
src/cas/example/iocmonitor/tsHash.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef tsDLHashList_H
|
||||
#define tsDLHashList_H
|
||||
|
||||
/*
|
||||
* Author: Jim Kowalkowski
|
||||
* Date: 7/96
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "gpHash.h"
|
||||
}
|
||||
|
||||
#include "tsDLList.h"
|
||||
|
||||
template <class T>
|
||||
class tsHash
|
||||
{
|
||||
private:
|
||||
void* hash_table;
|
||||
friend class tsDLHashIter<T>;
|
||||
|
||||
public:
|
||||
tsHash(void)
|
||||
{
|
||||
hash_table=0;
|
||||
gphInitPvt(&hash_table,2048); // 2048 is a guess
|
||||
}
|
||||
|
||||
~tsHash(void)
|
||||
{
|
||||
gphFreeMem(hash_table);
|
||||
}
|
||||
|
||||
int add(const char* key, T& item)
|
||||
{
|
||||
GPHENTRY* entry;
|
||||
int rc;
|
||||
|
||||
entry=gphAdd(hash_table,(char*)key,hash_table);
|
||||
|
||||
if(entry==0)
|
||||
rc=-1;
|
||||
else
|
||||
{
|
||||
entry->userPvt=(void*)&item;
|
||||
rc=0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int remove(const char* key,T*& item)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if(find(key,item)<0)
|
||||
rc=-1;
|
||||
else
|
||||
{
|
||||
gphDelete(hash_table,(char*)key,hash_table);
|
||||
rc=0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int find(const char* key, T*& item)
|
||||
{
|
||||
GPHENTRY* entry;
|
||||
int rc;
|
||||
|
||||
entry=gphFind(hash_table,(char*)key,hash_table);
|
||||
|
||||
if(entry==0)
|
||||
rc=-1;
|
||||
else
|
||||
{
|
||||
item=(T*)entry->userPvt;
|
||||
rc=0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class tsDLHashList : public tsDLList<T>
|
||||
{
|
||||
private:
|
||||
tsHash<T> h;
|
||||
friend class tsDLHashIter<T>;
|
||||
|
||||
public:
|
||||
tsDLHashList(void) { }
|
||||
~tsDLHashList(void) { }
|
||||
|
||||
int add(const char* key, T& item)
|
||||
{
|
||||
int rc;
|
||||
rc=h.add(key,item);
|
||||
tsDLList<T>::add(item);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int find(const char* key, T*& item)
|
||||
{
|
||||
int rc=0;
|
||||
if(h.find(key,item)!=0)
|
||||
rc=-1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int remove(const char* key,T*& item)
|
||||
{
|
||||
int rc=0;
|
||||
if(h.find(key,item)==0)
|
||||
{
|
||||
h.remove(key,item);
|
||||
tsDLList<T>::remove(*item);
|
||||
}
|
||||
else
|
||||
rc=-1;
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class tsDLHashNode : public tsDLNode<T>
|
||||
{
|
||||
public:
|
||||
T* getNext(void) { return tsDLNode<T>::getNext(); }
|
||||
T* getPrev(void) { return tsDLNode<T>::getPrev(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -21,6 +21,9 @@ PROD := excas
|
||||
|
||||
include $(TOP)/config/RULES.Host
|
||||
|
||||
pexcas: $(PROD_OBJS) $(PRODDEPLIBS)
|
||||
$(PURIFY) $(PROD_LINKER) $(PROD_OBJS) $(LDLIBS)
|
||||
|
||||
clean::
|
||||
@$(RM) excas
|
||||
@$(RM) fexcas
|
||||
|
||||
@@ -4,16 +4,7 @@
|
||||
// (asynchrronous process variable)
|
||||
//
|
||||
|
||||
#include <exServer.h>
|
||||
|
||||
//
|
||||
// exAsyncPV::maxSimultAsyncOps()
|
||||
// (virtual replacement for the default)
|
||||
//
|
||||
unsigned exAsyncPV::maxSimultAsyncOps () const
|
||||
{
|
||||
return 500u;
|
||||
}
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// exAsyncPV::read()
|
||||
@@ -23,6 +14,12 @@ caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
|
||||
{
|
||||
exAsyncReadIO *pIO;
|
||||
|
||||
if (this->simultAsychIOCount>=maxSimultAsyncIO) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncReadIO(ctx, *this, valueIn);
|
||||
if (!pIO) {
|
||||
return S_casApp_noMemory;
|
||||
@@ -39,6 +36,12 @@ caStatus exAsyncPV::write (const casCtx &ctx, gdd &valueIn)
|
||||
{
|
||||
exAsyncWriteIO *pIO;
|
||||
|
||||
if (this->simultAsychIOCount>=maxSimultAsyncIO) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
pIO = new exAsyncWriteIO(ctx, *this, valueIn);
|
||||
if (!pIO) {
|
||||
return S_casApp_noMemory;
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
// Example EPICS CA server
|
||||
//
|
||||
|
||||
#include <exServer.h>
|
||||
#include "exServer.h"
|
||||
|
||||
|
||||
@@ -2,25 +2,33 @@
|
||||
// Example EPICS CA server
|
||||
//
|
||||
|
||||
#include <exServer.h>
|
||||
#include <gddApps.h>
|
||||
#include "exServer.h"
|
||||
#include "gddApps.h"
|
||||
|
||||
osiTime exPV::currentTime;
|
||||
|
||||
//
|
||||
// exPV::exPV()
|
||||
//
|
||||
exPV::exPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exPV::exPV (caServer &casIn, pvInfo &setup, aitBool preCreateFlag) :
|
||||
pValue(NULL),
|
||||
pScanTimer(NULL),
|
||||
info(setup),
|
||||
casPV(ctxIn, setup.getName().string()),
|
||||
interest(aitFalse)
|
||||
casPV(casIn),
|
||||
interest(aitFalse),
|
||||
preCreate(preCreateFlag)
|
||||
{
|
||||
//
|
||||
// no dataless PV allowed
|
||||
//
|
||||
assert (this->info.getElementCount()>=1u);
|
||||
|
||||
//
|
||||
// start a very slow background scan
|
||||
// (we will speed this up to the normal rate when
|
||||
// someone is watching the PV)
|
||||
//
|
||||
this->pScanTimer =
|
||||
new exScanTimer (this->getScanPeriod(), *this);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -36,6 +44,19 @@ exPV::~exPV()
|
||||
this->pValue->unreference();
|
||||
this->pValue = NULL;
|
||||
}
|
||||
this->info.destroyPV();
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::destroy()
|
||||
// this is replaced by a noop since we are
|
||||
// pre-creating most of the PVs during init in this simple server
|
||||
//
|
||||
void exPV::destroy()
|
||||
{
|
||||
if (!this->preCreate) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -65,7 +86,8 @@ caStatus exPV::update(gdd &valueIn)
|
||||
return cas;
|
||||
}
|
||||
|
||||
cur.get (t.tv_sec, t.tv_nsec);
|
||||
t.tv_sec = (time_t) cur.getSecTruncToLong ();
|
||||
t.tv_nsec = cur.getNSecTruncToLong ();
|
||||
this->pValue->setTimeStamp(&t);
|
||||
this->pValue->setStat (epicsAlarmNone);
|
||||
this->pValue->setSevr (epicsSevNone);
|
||||
@@ -102,7 +124,7 @@ osiBool exScanTimer::again() const
|
||||
//
|
||||
const osiTime exScanTimer::delay() const
|
||||
{
|
||||
return pv.getScanRate();
|
||||
return pv.getScanPeriod();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -132,19 +154,26 @@ caStatus exPV::interestRegister()
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
if (!this->pScanTimer) {
|
||||
this->interest = aitTrue;
|
||||
|
||||
//
|
||||
// If a slow scan is pending then reschedule it
|
||||
// with the specified scan period.
|
||||
//
|
||||
if (this->pScanTimer) {
|
||||
this->pScanTimer->reschedule(this->info.getScanPeriod());
|
||||
}
|
||||
else {
|
||||
this->pScanTimer = new exScanTimer
|
||||
(this->info.getScanRate(), *this);
|
||||
(this->info.getScanPeriod(), *this);
|
||||
if (!this->pScanTimer) {
|
||||
errPrintf (S_cas_noMemory, __FILE__, __LINE__,
|
||||
"Scan init for %s failed\n",
|
||||
this->info.getName().string());
|
||||
this->info.getName());
|
||||
return S_cas_noMemory;
|
||||
}
|
||||
}
|
||||
|
||||
this->interest = aitTrue;
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
@@ -153,17 +182,16 @@ caStatus exPV::interestRegister()
|
||||
//
|
||||
void exPV::interestDelete()
|
||||
{
|
||||
if (this->pScanTimer) {
|
||||
delete this->pScanTimer;
|
||||
this->pScanTimer = NULL;
|
||||
}
|
||||
this->interest = aitFalse;
|
||||
if (this->pScanTimer) {
|
||||
this->pScanTimer->reschedule(this->getScanPeriod());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::show()
|
||||
//
|
||||
void exPV::show(unsigned level)
|
||||
void exPV::show(unsigned level) const
|
||||
{
|
||||
if (level>1u) {
|
||||
if (this->pValue) {
|
||||
@@ -215,7 +243,8 @@ inline aitTimeStamp exPV::getTS()
|
||||
}
|
||||
else {
|
||||
osiTime cur(osiTime::getCurrent());
|
||||
cur.get(ts.tv_sec, ts.tv_nsec);
|
||||
ts.tv_sec = (time_t) cur.getSecTruncToLong ();
|
||||
ts.tv_nsec = cur.getNSecTruncToLong ();
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
|
||||
#include <exServer.h>
|
||||
#include <gddApps.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "exServer.h"
|
||||
#include "gddApps.h"
|
||||
|
||||
#define myPI 3.14159265358979323846
|
||||
|
||||
//
|
||||
@@ -31,7 +32,7 @@ void exScalarPV::scan()
|
||||
gdd *pDD;
|
||||
float newValue;
|
||||
float limit;
|
||||
|
||||
|
||||
//
|
||||
// update current time (so we are not required to do
|
||||
// this every time that we write the PV which impacts
|
||||
@@ -54,9 +55,9 @@ void exScalarPV::scan()
|
||||
}
|
||||
newValue += (float) (sin (radians) / 10.0);
|
||||
limit = (float) this->info.getHopr();
|
||||
newValue = min (newValue, limit);
|
||||
newValue = tsMin (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = max (newValue, limit);
|
||||
newValue = tsMax (newValue, limit);
|
||||
*pDD = newValue;
|
||||
status = this->update (*pDD);
|
||||
if (status) {
|
||||
|
||||
@@ -7,124 +7,272 @@
|
||||
// Example EPICS CA server
|
||||
//
|
||||
|
||||
#include <exServer.h>
|
||||
|
||||
const pvInfo exServer::pvList[] = {
|
||||
pvInfo (1.0e-1, "jane", 10.0f, 0.0f, excasIoSync, 1u),
|
||||
pvInfo (2.0, "fred", 10.0f, -10.0f, excasIoSync, 1u),
|
||||
pvInfo (1.0e-1, "janet", 10.0f, 0.0f, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "freddy", 10.0f, -10.0f, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "alan", 10.0f, -10.0f, excasIoSync, 100u),
|
||||
pvInfo (20.0, "albert", 10.0f, -10.0f, excasIoSync, 1000u)
|
||||
};
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// static data for exServer
|
||||
//
|
||||
gddAppFuncTable<exPV> exServer::ft;
|
||||
|
||||
//
|
||||
// static list of pre-created PVs
|
||||
//
|
||||
pvInfo exServer::pvList[] = {
|
||||
pvInfo (1.0e-1, "jane", 10.0f, 0.0f, excasIoSync, 1u),
|
||||
pvInfo (2.0, "fred", 10.0f, -10.0f, excasIoSync, 1u),
|
||||
pvInfo (1.0e-1, "janet", 10.0f, 0.0f, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "freddy", 10.0f, -10.0f, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "alan", 10.0f, -10.0f, excasIoSync, 100u),
|
||||
pvInfo (20.0, "albert", 10.0f, -10.0f, excasIoSync, 1000u)
|
||||
};
|
||||
//
|
||||
// static on-the-fly PVs
|
||||
//
|
||||
pvInfo exServer::bill (2.0, "bill", 10.0f, -10.0f, excasIoSync, 1u);
|
||||
pvInfo exServer::billy (2.0, "billy", 10.0f, -10.0f, excasIoAsync, 1u);
|
||||
|
||||
//
|
||||
// exServer::exServer()
|
||||
//
|
||||
exServer::exServer(unsigned pvMaxNameLength, unsigned pvCountEstimate,
|
||||
unsigned maxSimultaneousIO) :
|
||||
caServer(pvMaxNameLength, pvCountEstimate, maxSimultaneousIO)
|
||||
exServer::exServer(const char * const pvPrefix, unsigned aliasCount) :
|
||||
caServer(NELEMENTS(this->pvList)+2u),
|
||||
simultAsychIOCount(0u)
|
||||
{
|
||||
ft.installReadFunc("status",exPV::getStatus);
|
||||
ft.installReadFunc("severity",exPV::getSeverity);
|
||||
ft.installReadFunc("seconds",exPV::getSeconds);
|
||||
ft.installReadFunc("nanoseconds",exPV::getNanoseconds);
|
||||
ft.installReadFunc("precision",exPV::getPrecision);
|
||||
ft.installReadFunc("graphicHigh",exPV::getHighLimit);
|
||||
ft.installReadFunc("graphicLow",exPV::getLowLimit);
|
||||
ft.installReadFunc("controlHigh",exPV::getHighLimit);
|
||||
ft.installReadFunc("controlLow",exPV::getLowLimit);
|
||||
ft.installReadFunc("alarmHigh",exPV::getHighLimit);
|
||||
ft.installReadFunc("alarmLow",exPV::getLowLimit);
|
||||
ft.installReadFunc("alarmHighWarning",exPV::getHighLimit);
|
||||
ft.installReadFunc("alarmLowWarning",exPV::getLowLimit);
|
||||
ft.installReadFunc("units",exPV::getUnits);
|
||||
ft.installReadFunc("value",exPV::getValue);
|
||||
ft.installReadFunc("enums",exPV::getEnums);
|
||||
unsigned i;
|
||||
exPV *pPV;
|
||||
pvInfo *pPVI;
|
||||
pvInfo *pPVAfter =
|
||||
&exServer::pvList[NELEMENTS(exServer::pvList)];
|
||||
int resLibStatus;
|
||||
char pvAlias[256];
|
||||
const char * const pNameFmtStr = "%.100s%.20s";
|
||||
const char * const pAliasFmtStr = "%.100s%.20s%u";
|
||||
|
||||
ft.installReadFunc ("status", &exPV::getStatus);
|
||||
ft.installReadFunc ("severity", &exPV::getSeverity);
|
||||
ft.installReadFunc ("seconds", &exPV::getSeconds);
|
||||
ft.installReadFunc ("nanoseconds", &exPV::getNanoseconds);
|
||||
ft.installReadFunc ("precision", &exPV::getPrecision);
|
||||
ft.installReadFunc ("graphicHigh", &exPV::getHighLimit);
|
||||
ft.installReadFunc ("graphicLow", &exPV::getLowLimit);
|
||||
ft.installReadFunc ("controlHigh", &exPV::getHighLimit);
|
||||
ft.installReadFunc ("controlLow", &exPV::getLowLimit);
|
||||
ft.installReadFunc ("alarmHigh", &exPV::getHighLimit);
|
||||
ft.installReadFunc ("alarmLow", &exPV::getLowLimit);
|
||||
ft.installReadFunc ("alarmHighWarning", &exPV::getHighLimit);
|
||||
ft.installReadFunc ("alarmLowWarning", &exPV::getLowLimit);
|
||||
ft.installReadFunc ("units", &exPV::getUnits);
|
||||
ft.installReadFunc ("value", &exPV::getValue);
|
||||
ft.installReadFunc ("enums", &exPV::getEnums);
|
||||
|
||||
//
|
||||
// hash table size may need adjustment here?
|
||||
//
|
||||
resLibStatus = this->stringResTbl.init(NELEMENTS(this->pvList)*(aliasCount+1u)+2u);
|
||||
if (resLibStatus) {
|
||||
fprintf(stderr, "CAS: string resource id table init failed\n");
|
||||
//
|
||||
// should throw an exception once this is portable
|
||||
//
|
||||
assert(resLibStatus==0);
|
||||
}
|
||||
|
||||
//
|
||||
// pre-create all of the simple PVs that this server will export
|
||||
//
|
||||
for (pPVI = exServer::pvList; pPVI < pPVAfter; pPVI++) {
|
||||
pPV = pPVI->createPV (*this, aitTrue);
|
||||
if (!pPV) {
|
||||
fprintf(stderr, "Unable to create new PV \"%s\"\n",
|
||||
pPVI->getName());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Install canonical (root) name
|
||||
//
|
||||
sprintf(pvAlias, pNameFmtStr, pvPrefix, pPVI->getName());
|
||||
this->installAliasName(*pPVI, pvAlias);
|
||||
|
||||
//
|
||||
// Install numbered alias names
|
||||
//
|
||||
for (i=0u; i<aliasCount; i++) {
|
||||
sprintf(pvAlias, pAliasFmtStr, pvPrefix,
|
||||
pPVI->getName(), i);
|
||||
this->installAliasName(*pPVI, pvAlias);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Install create on-the-fly PVs
|
||||
// into the PV name hash table
|
||||
//
|
||||
sprintf(pvAlias, pNameFmtStr, pvPrefix, bill.getName());
|
||||
this->installAliasName(bill, pvAlias);
|
||||
sprintf(pvAlias, pNameFmtStr, pvPrefix, billy.getName());
|
||||
this->installAliasName(billy, pvAlias);
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::installAliasName()
|
||||
//
|
||||
void exServer::installAliasName(pvInfo &info, const char *pAliasName)
|
||||
{
|
||||
pvEntry *pEntry;
|
||||
|
||||
pEntry = new pvEntry(info, *this, pAliasName);
|
||||
if (pEntry) {
|
||||
int resLibStatus;
|
||||
resLibStatus = this->stringResTbl.add(*pEntry);
|
||||
if (resLibStatus==0) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
delete pEntry;
|
||||
}
|
||||
}
|
||||
fprintf(stderr,
|
||||
"Unable to enter PV=\"%s\" Alias=\"%s\" in PV name alias hash table\n",
|
||||
info.getName(), pAliasName);
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::pvExistTest()
|
||||
//
|
||||
pvExistReturn exServer::pvExistTest(const casCtx &ctxIn, const char *pPVName)
|
||||
pvExistReturn exServer::pvExistTest
|
||||
(const casCtx& ctxIn, const char *pPVName)
|
||||
{
|
||||
const pvInfo *pPVI;
|
||||
//
|
||||
// lifetime of id is shorter than lifetime of pName
|
||||
//
|
||||
stringId id(pPVName, stringId::refString);
|
||||
pvEntry *pPVE;
|
||||
|
||||
pPVI = exServer::findPV(pPVName);
|
||||
if (pPVI) {
|
||||
if (pPVI->getIOType()==excasIoAsync) {
|
||||
exAsyncExistIO *pIO;
|
||||
pIO = new exAsyncExistIO(*pPVI, ctxIn);
|
||||
if (pIO) {
|
||||
return pvExistReturn(S_casApp_asyncCompletion);
|
||||
}
|
||||
else {
|
||||
return pvExistReturn(S_casApp_noMemory);
|
||||
}
|
||||
}
|
||||
|
||||
const char *pName = pPVI->getName();
|
||||
return pvExistReturn(S_casApp_success, pName);
|
||||
//
|
||||
// Look in hash table for PV name (or PV alias name)
|
||||
//
|
||||
pPVE = this->stringResTbl.lookup(id);
|
||||
if (!pPVE) {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
|
||||
return pvExistReturn(S_casApp_pvNotFound);
|
||||
}
|
||||
pvInfo &pvi = pPVE->getInfo();
|
||||
|
||||
//
|
||||
// findPV()
|
||||
//
|
||||
const pvInfo *exServer::findPV(const char *pName)
|
||||
{
|
||||
const pvInfo *pPVI;
|
||||
const pvInfo *pPVAfter =
|
||||
&exServer::pvList[NELEMENTS(exServer::pvList)];
|
||||
//
|
||||
// Initiate async IO if this is an async PV
|
||||
//
|
||||
if (pvi.getIOType() == excasIoSync) {
|
||||
return pverExistsHere;
|
||||
}
|
||||
else {
|
||||
if (this->simultAsychIOCount>=maxSimultAsyncIO) {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
|
||||
for (pPVI = exServer::pvList; pPVI < pPVAfter; pPVI++) {
|
||||
if (strcmp (pName, pPVI->getName().string()) == '\0') {
|
||||
return pPVI;
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
exAsyncExistIO *pIO;
|
||||
pIO = new exAsyncExistIO(pvi, ctxIn, *this);
|
||||
if (pIO) {
|
||||
return pverAsyncCompletion;
|
||||
}
|
||||
else {
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::createPV()
|
||||
//
|
||||
casPV *exServer::createPV (const casCtx &ctxIn, const char *pPVName)
|
||||
pvCreateReturn exServer::createPV
|
||||
(const casCtx &ctx, const char *pName)
|
||||
{
|
||||
const pvInfo *pInfo;
|
||||
exPV *pPV;
|
||||
//
|
||||
// lifetime of id is shorter than lifetime of pName
|
||||
//
|
||||
stringId id(pName, stringId::refString);
|
||||
exPV *pPV;
|
||||
pvEntry *pPVE;
|
||||
|
||||
pInfo = exServer::findPV(pPVName);
|
||||
if (!pInfo) {
|
||||
return NULL;
|
||||
pPVE = this->stringResTbl.lookup(id);
|
||||
if (!pPVE) {
|
||||
return S_casApp_pvNotFound;
|
||||
}
|
||||
|
||||
pvInfo &pvi = pPVE->getInfo();
|
||||
|
||||
//
|
||||
// If this is a synchronous PV create the PV now
|
||||
//
|
||||
if (pvi.getIOType() == excasIoSync) {
|
||||
pPV = pvi.createPV(*this, aitFalse);
|
||||
if (pPV) {
|
||||
return *pPV;
|
||||
}
|
||||
else {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
// Initiate async IO if this is an async PV
|
||||
//
|
||||
else {
|
||||
if (this->simultAsychIOCount>=maxSimultAsyncIO) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
exAsyncCreateIO *pIO =
|
||||
new exAsyncCreateIO(pvi, *this, ctx);
|
||||
if (pIO) {
|
||||
return S_casApp_asyncCompletion;
|
||||
}
|
||||
else {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// pvInfo::createPV()
|
||||
//
|
||||
exPV *pvInfo::createPV (exServer &exCAS, aitBool preCreateFlag)
|
||||
{
|
||||
if (this->pPV) {
|
||||
return this->pPV;
|
||||
}
|
||||
|
||||
exPV *pNewPV;
|
||||
|
||||
//
|
||||
// create an instance of the appropriate class
|
||||
// depending on the io type and the number
|
||||
// of elements
|
||||
//
|
||||
if (pInfo->getElementCount()==1u) {
|
||||
switch (pInfo->getIOType()){
|
||||
if (this->elementCount==1u) {
|
||||
switch (this->ioType){
|
||||
case excasIoSync:
|
||||
pPV = new exScalarPV (ctxIn, *pInfo);
|
||||
pNewPV = new exScalarPV (exCAS, *this, preCreateFlag);
|
||||
break;
|
||||
case excasIoAsync:
|
||||
pPV = new exAsyncPV (ctxIn, *pInfo);
|
||||
pNewPV = new exAsyncPV (exCAS, *this, preCreateFlag);
|
||||
break;
|
||||
default:
|
||||
pPV = NULL;
|
||||
pNewPV = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pPV = new exVectorPV (ctxIn, *pInfo);
|
||||
if (this->ioType==excasIoSync) {
|
||||
pNewPV = new exVectorPV (exCAS, *this, preCreateFlag);
|
||||
}
|
||||
else {
|
||||
pNewPV = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -132,21 +280,23 @@ casPV *exServer::createPV (const casCtx &ctxIn, const char *pPVName)
|
||||
// the constructor because the base class's
|
||||
// pure virtual function would be called)
|
||||
//
|
||||
if (pPV) {
|
||||
pPV->scan();
|
||||
if (pNewPV) {
|
||||
this->pPV = pNewPV;
|
||||
pNewPV->scan();
|
||||
}
|
||||
|
||||
return pPV;
|
||||
return pNewPV;
|
||||
}
|
||||
|
||||
//
|
||||
// exServer::show()
|
||||
// exServer::show()
|
||||
//
|
||||
void exServer::show (unsigned level)
|
||||
void exServer::show (unsigned level) const
|
||||
{
|
||||
//
|
||||
// server tool specific show code goes here
|
||||
//
|
||||
this->stringResTbl.show(level);
|
||||
|
||||
//
|
||||
// print information about ca server libarary
|
||||
@@ -170,12 +320,10 @@ void exOSITimer::destroy()
|
||||
//
|
||||
void exAsyncExistIO::expire()
|
||||
{
|
||||
const char *pName = pvi.getName();
|
||||
|
||||
//
|
||||
// post IO completion
|
||||
//
|
||||
this->postIOCompletion (pvExistReturn(S_cas_success, pName));
|
||||
this->postIOCompletion (pverExistsHere);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -186,3 +334,28 @@ const char *exAsyncExistIO::name() const
|
||||
return "exAsyncExistIO";
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncCreateIO::expire()
|
||||
// (a virtual function that runs when the base timer expires)
|
||||
//
|
||||
void exAsyncCreateIO::expire()
|
||||
{
|
||||
exPV *pPV;
|
||||
|
||||
pPV = this->pvi.createPV(this->cas, aitFalse);
|
||||
if (pPV) {
|
||||
this->postIOCompletion (pvCreateReturn(*pPV));
|
||||
}
|
||||
else {
|
||||
this->postIOCompletion (pvCreateReturn(S_casApp_noMemory));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exAsyncCreateIO::name()
|
||||
//
|
||||
const char *exAsyncCreateIO::name() const
|
||||
{
|
||||
return "exAsyncCreateIO";
|
||||
}
|
||||
|
||||
|
||||
@@ -26,37 +26,38 @@
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#include <epicsAssert.h>
|
||||
#include <casdef.h>
|
||||
#include <gddAppFuncTable.h>
|
||||
#include <osiTimer.h>
|
||||
|
||||
#ifndef max
|
||||
#define max(A,B) ((A)<(B)?(B):(A))
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(A,B) ((A)>(B)?(B):(A))
|
||||
#endif
|
||||
#include "epicsAssert.h"
|
||||
#include "casdef.h"
|
||||
#include "gddAppFuncTable.h"
|
||||
#include "osiTimer.h"
|
||||
#include "resourceLib.h"
|
||||
#include "tsMinMax.h"
|
||||
|
||||
#ifndef NELEMENTS
|
||||
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
|
||||
#endif
|
||||
|
||||
#define LOCAL static
|
||||
#define maxSimultAsyncIO 1000u
|
||||
|
||||
//
|
||||
// info about all pv in this server
|
||||
//
|
||||
enum excasIoType {excasIoSync, excasIoAsync};
|
||||
|
||||
class exPV;
|
||||
class exServer;
|
||||
|
||||
//
|
||||
// pvInfo
|
||||
//
|
||||
class pvInfo {
|
||||
public:
|
||||
pvInfo (double scanRateIn, const char *pName,
|
||||
pvInfo (double scanPeriodIn, const char *pNameIn,
|
||||
aitFloat32 hoprIn, aitFloat32 loprIn,
|
||||
excasIoType ioTypeIn, unsigned countIn) :
|
||||
scanRate(scanRateIn), name(pName), hopr(hoprIn),
|
||||
lopr(loprIn), ioType(ioTypeIn), elementCount(countIn)
|
||||
scanPeriod(scanPeriodIn), pName(pNameIn),
|
||||
hopr(hoprIn), lopr(loprIn), ioType(ioTypeIn),
|
||||
elementCount(countIn), pPV(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,29 +66,61 @@ public:
|
||||
// for this class
|
||||
//
|
||||
pvInfo (const pvInfo ©In) :
|
||||
scanRate(copyIn.scanRate), name(copyIn.name),
|
||||
hopr(copyIn.hopr), lopr(copyIn.lopr),
|
||||
ioType(copyIn.ioType), elementCount(copyIn.elementCount)
|
||||
scanPeriod(copyIn.scanPeriod), pName(copyIn.pName),
|
||||
hopr(copyIn.hopr), lopr(copyIn.lopr),
|
||||
ioType(copyIn.ioType), elementCount(copyIn.elementCount),
|
||||
pPV(copyIn.pPV)
|
||||
{
|
||||
}
|
||||
|
||||
const double getScanRate () const { return this->scanRate; }
|
||||
const aitString &getName () const { return this->name; }
|
||||
const double getScanPeriod () const { return this->scanPeriod; }
|
||||
const char *getName () const { return this->pName; }
|
||||
const double getHopr () const { return this->hopr; }
|
||||
const double getLopr () const { return this->lopr; }
|
||||
const excasIoType getIOType () const { return this->ioType; }
|
||||
const unsigned getElementCount() const { return this->elementCount; }
|
||||
const unsigned getElementCount() const
|
||||
{ return this->elementCount; }
|
||||
void destroyPV() { this->pPV=NULL; }
|
||||
exPV *createPV (exServer &exCAS, aitBool preCreateFlag);
|
||||
private:
|
||||
const double scanRate;
|
||||
const aitString name;
|
||||
const double scanPeriod;
|
||||
const char *pName;
|
||||
const double hopr;
|
||||
const double lopr;
|
||||
const excasIoType ioType;
|
||||
const unsigned elementCount;
|
||||
exPV *pPV;
|
||||
};
|
||||
|
||||
class exPV;
|
||||
//
|
||||
// pvEntry
|
||||
//
|
||||
// o entry in the string hash table for the pvInfo
|
||||
// o Since there may be aliases then we may end up
|
||||
// with several of this class all referencing
|
||||
// the same pv info class (justification
|
||||
// for this breaking out into a seperate class
|
||||
// from pvInfo)
|
||||
//
|
||||
class pvEntry : public stringId, public tsSLNode<pvEntry> {
|
||||
public:
|
||||
pvEntry (pvInfo &infoIn, exServer &casIn,
|
||||
const char *pAliasName) :
|
||||
stringId(pAliasName), info(infoIn), cas(casIn)
|
||||
{
|
||||
assert(this->stringId::resourceName()!=NULL);
|
||||
}
|
||||
|
||||
inline ~pvEntry();
|
||||
|
||||
pvInfo &getInfo() const { return this->info; }
|
||||
|
||||
inline void destroy ();
|
||||
|
||||
private:
|
||||
pvInfo &info;
|
||||
exServer &cas;
|
||||
};
|
||||
|
||||
//
|
||||
// exScanTimer
|
||||
@@ -107,13 +140,12 @@ private:
|
||||
//
|
||||
// exPV
|
||||
//
|
||||
class exPV : public casPV {
|
||||
|
||||
class exPV : public casPV, public tsSLNode<exPV> {
|
||||
public:
|
||||
exPV (const casCtx &ctxIn, const pvInfo &setup);
|
||||
exPV (caServer &cas, pvInfo &setup, aitBool preCreateFlag);
|
||||
virtual ~exPV();
|
||||
|
||||
void show(unsigned level);
|
||||
void show(unsigned level) const;
|
||||
|
||||
//
|
||||
// Called by the server libary each time that it wishes to
|
||||
@@ -170,20 +202,43 @@ public:
|
||||
//
|
||||
aitTimeStamp getTS();
|
||||
|
||||
const float getScanRate()
|
||||
//
|
||||
// If no one is watching scan the PV with 10.0
|
||||
// times the specified period
|
||||
//
|
||||
const float getScanPeriod()
|
||||
{
|
||||
return this->info.getScanRate();
|
||||
double curPeriod;
|
||||
|
||||
curPeriod = this->info.getScanPeriod();
|
||||
if (!this->interest) {
|
||||
curPeriod *= 10.0L;
|
||||
}
|
||||
return curPeriod;
|
||||
}
|
||||
|
||||
caStatus read (const casCtx &, gdd &protoIn);
|
||||
|
||||
caStatus write (const casCtx &, gdd &protoIn);
|
||||
|
||||
void destroy();
|
||||
|
||||
const pvInfo &getPVInfo()
|
||||
{
|
||||
return this->info;
|
||||
}
|
||||
|
||||
const char *getName() const
|
||||
{
|
||||
return this->info.getName();
|
||||
}
|
||||
|
||||
protected:
|
||||
gdd *pValue;
|
||||
exScanTimer *pScanTimer;
|
||||
const pvInfo & info;
|
||||
pvInfo & info;
|
||||
aitBool interest;
|
||||
aitBool preCreate;
|
||||
static osiTime currentTime;
|
||||
|
||||
virtual caStatus updateValue (gdd &value) = 0;
|
||||
@@ -194,8 +249,9 @@ protected:
|
||||
//
|
||||
class exScalarPV : public exPV {
|
||||
public:
|
||||
exScalarPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exPV (ctxIn, setup) {}
|
||||
exScalarPV (caServer &cas,
|
||||
pvInfo &setup, aitBool preCreateFlag) :
|
||||
exPV (cas, setup, preCreateFlag) {}
|
||||
void scan();
|
||||
private:
|
||||
caStatus updateValue (gdd &value);
|
||||
@@ -206,8 +262,9 @@ private:
|
||||
//
|
||||
class exVectorPV : public exPV {
|
||||
public:
|
||||
exVectorPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exPV (ctxIn, setup) {}
|
||||
exVectorPV (caServer &cas, pvInfo &setup,
|
||||
aitBool preCreateFlag) :
|
||||
exPV (cas, setup, preCreateFlag) {}
|
||||
void scan();
|
||||
|
||||
unsigned maxDimension() const;
|
||||
@@ -222,20 +279,47 @@ private:
|
||||
//
|
||||
class exServer : public caServer {
|
||||
public:
|
||||
exServer(unsigned pvMaxNameLength, unsigned pvCountEstimate=0x3ff,
|
||||
unsigned maxSimultaneousIO=1u);
|
||||
void show (unsigned level);
|
||||
pvExistReturn pvExistTest (const casCtx &ctxIn, const char *pPVName);
|
||||
casPV *createPV (const casCtx &ctxIn, const char *pPVName);
|
||||
exServer(const char * const pvPrefix, unsigned aliasCount);
|
||||
void show (unsigned level) const;
|
||||
pvExistReturn pvExistTest (const casCtx&, const char *pPVName);
|
||||
pvCreateReturn createPV (const casCtx &ctx, const char *pPVName);
|
||||
|
||||
static const pvInfo *findPV(const char *pName);
|
||||
void installAliasName(pvInfo &info, const char *pAliasName);
|
||||
inline void removeAliasName(pvEntry &entry);
|
||||
|
||||
static gddAppFuncTableStatus read(exPV &pv, gdd &value)
|
||||
{
|
||||
return exServer::ft.read(pv, value);
|
||||
}
|
||||
|
||||
//
|
||||
// removeIO
|
||||
//
|
||||
void removeIO()
|
||||
{
|
||||
if (this->simultAsychIOCount>0u) {
|
||||
this->simultAsychIOCount--;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"simultAsychIOCount underflow?\n");
|
||||
}
|
||||
}
|
||||
private:
|
||||
static const pvInfo pvList[];
|
||||
resTable<pvEntry,stringId> stringResTbl;
|
||||
unsigned simultAsychIOCount;
|
||||
|
||||
//
|
||||
// list of pre-created PVs
|
||||
//
|
||||
static pvInfo pvList[];
|
||||
|
||||
//
|
||||
// on-the-fly PVs
|
||||
//
|
||||
static pvInfo bill;
|
||||
static pvInfo billy;
|
||||
|
||||
static gddAppFuncTable<exPV> ft;
|
||||
};
|
||||
|
||||
@@ -247,8 +331,9 @@ public:
|
||||
//
|
||||
// exAsyncPV()
|
||||
//
|
||||
exAsyncPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exScalarPV (ctxIn, setup) {}
|
||||
exAsyncPV (caServer &cas, pvInfo &setup, aitBool preCreateFlag) :
|
||||
exScalarPV (cas, setup, preCreateFlag),
|
||||
simultAsychIOCount(0u) {}
|
||||
|
||||
//
|
||||
// read
|
||||
@@ -260,8 +345,20 @@ public:
|
||||
//
|
||||
caStatus write(const casCtx &ctxIn, gdd &value);
|
||||
|
||||
unsigned maxSimultAsyncOps () const;
|
||||
//
|
||||
// removeIO
|
||||
//
|
||||
void removeIO()
|
||||
{
|
||||
if (this->simultAsychIOCount>0u) {
|
||||
this->simultAsychIOCount--;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "inconsistent simultAsychIOCount?\n");
|
||||
}
|
||||
}
|
||||
private:
|
||||
unsigned simultAsychIOCount;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -332,6 +429,7 @@ public:
|
||||
|
||||
~exAsyncWriteIO()
|
||||
{
|
||||
this->pv.removeIO();
|
||||
this->value.unreference();
|
||||
}
|
||||
|
||||
@@ -365,6 +463,7 @@ public:
|
||||
|
||||
~exAsyncReadIO()
|
||||
{
|
||||
this->pv.removeIO();
|
||||
this->proto.unreference();
|
||||
}
|
||||
|
||||
@@ -391,8 +490,14 @@ public:
|
||||
//
|
||||
// exAsyncExistIO()
|
||||
//
|
||||
exAsyncExistIO(const pvInfo &pviIn, const casCtx &ctxIn) :
|
||||
casAsyncPVExistIO(ctxIn), pvi(pviIn) {}
|
||||
exAsyncExistIO(const pvInfo &pviIn, const casCtx &ctxIn,
|
||||
exServer &casIn) :
|
||||
casAsyncPVExistIO(ctxIn), pvi(pviIn), cas(casIn) {}
|
||||
|
||||
~exAsyncExistIO()
|
||||
{
|
||||
this->cas.removeIO();
|
||||
}
|
||||
|
||||
//
|
||||
// expire()
|
||||
@@ -404,6 +509,67 @@ public:
|
||||
const char *name() const;
|
||||
private:
|
||||
const pvInfo &pvi;
|
||||
exServer &cas;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// exAsyncCreateIO
|
||||
// (PV create async IO)
|
||||
//
|
||||
class exAsyncCreateIO : public casAsyncPVCreateIO, public exOSITimer {
|
||||
public:
|
||||
//
|
||||
// exAsyncCreateIO()
|
||||
//
|
||||
exAsyncCreateIO(pvInfo &pviIn, exServer &casIn,
|
||||
const casCtx &ctxIn) :
|
||||
casAsyncPVCreateIO(ctxIn), pvi(pviIn), cas(casIn) {}
|
||||
|
||||
~exAsyncCreateIO()
|
||||
{
|
||||
this->cas.removeIO();
|
||||
}
|
||||
|
||||
//
|
||||
// expire()
|
||||
// (a virtual function that runs when the base timer expires)
|
||||
// see exServer.cc
|
||||
//
|
||||
void expire();
|
||||
|
||||
const char *name() const;
|
||||
private:
|
||||
pvInfo &pvi;
|
||||
exServer &cas;
|
||||
};
|
||||
|
||||
//
|
||||
// exServer::removeAliasName()
|
||||
//
|
||||
inline void exServer::removeAliasName(pvEntry &entry)
|
||||
{
|
||||
pvEntry *pE;
|
||||
pE = this->stringResTbl.remove(entry);
|
||||
assert(pE = &entry);
|
||||
}
|
||||
|
||||
//
|
||||
// pvEntry::~pvEntry()
|
||||
//
|
||||
inline pvEntry::~pvEntry()
|
||||
{
|
||||
this->cas.removeAliasName(*this);
|
||||
}
|
||||
|
||||
//
|
||||
// pvEntry:: destroy()
|
||||
//
|
||||
inline void pvEntry::destroy ()
|
||||
{
|
||||
//
|
||||
// always created with new
|
||||
//
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#include <exServer.h>
|
||||
#include <gddApps.h>
|
||||
#include "exServer.h"
|
||||
#include "gddApps.h"
|
||||
|
||||
#define myPI 3.14159265358979323846
|
||||
|
||||
@@ -104,9 +104,9 @@ void exVectorPV::scan()
|
||||
}
|
||||
newValue += (float) (sin (radians) / 10.0);
|
||||
limit = (float) this->info.getHopr();
|
||||
newValue = min (newValue, limit);
|
||||
newValue = tsMin (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = max (newValue, limit);
|
||||
newValue = tsMax (newValue, limit);
|
||||
*(pF++) = newValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
|
||||
#include <exServer.h>
|
||||
#include <fdManager.h>
|
||||
#include "exServer.h"
|
||||
#include "fdManager.h"
|
||||
|
||||
//
|
||||
// main()
|
||||
// (example single threaded ca server tool main loop)
|
||||
//
|
||||
int main (int argc, const char **argv)
|
||||
extern int main (int argc, const char **argv)
|
||||
{
|
||||
osiTime begin(osiTime::getCurrent());
|
||||
exServer *pCAS;
|
||||
unsigned debugLevel = 0u;
|
||||
float executionTime;
|
||||
char pvPrefix[128] = "";
|
||||
unsigned aliasCount = 1u;
|
||||
aitBool forever = aitTrue;
|
||||
int i;
|
||||
|
||||
@@ -23,12 +25,20 @@ int main (int argc, const char **argv)
|
||||
forever = aitFalse;
|
||||
continue;
|
||||
}
|
||||
printf ("usage: %s -d<debug level> -t<execution time>\n",
|
||||
if (sscanf(argv[i],"-p %127s", pvPrefix)==1) {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(argv[i],"-c %u", &aliasCount)==1) {
|
||||
continue;
|
||||
}
|
||||
printf (
|
||||
"usage: %s [-d<debug level> -t<execution time> -p<PV name prefix> -c<numbered alias count>]\n",
|
||||
argv[0]);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
pCAS = new exServer(32u,5u,500u);
|
||||
pCAS = new exServer(pvPrefix, aliasCount);
|
||||
if (!pCAS) {
|
||||
return (-1);
|
||||
}
|
||||
@@ -56,6 +66,7 @@ int main (int argc, const char **argv)
|
||||
delay = osiTime::getCurrent() - begin;
|
||||
}
|
||||
}
|
||||
pCAS->show(2u);
|
||||
delete pCAS;
|
||||
return (0);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user