Compare commits
137 Commits
R3.13.0-be
...
R3.13.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
2
Makefile
2
Makefile
@@ -30,5 +30,5 @@ built_release:
|
||||
|
||||
uninstall::
|
||||
@DIR1=`pwd`;cd $(INSTALL_LOCATION);DIR2=`pwd`;cd $$DIR1;\
|
||||
if [ "$$DIR1" != "$$DIR2" ]; then rm -fr $(INSTALL_LOCATION)/config; fi
|
||||
if [ "$$DIR1" != "$$DIR2" ]; then $(RMDIR) $(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!
|
||||
|
||||
|
||||
@@ -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,12 @@
|
||||
# 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
|
||||
|
||||
# overrides defines in CONFIG_SITE that don't fit Tornado
|
||||
#
|
||||
|
||||
@@ -3,54 +3,62 @@
|
||||
# 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
|
||||
|
||||
# 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
|
||||
CXX_OPT_FLAGS_YES = -Ox
|
||||
# -Zi : included debugging info
|
||||
CXX_OPT_FLAGS_NO = -Zi
|
||||
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 +69,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 +108,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 +119,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,
|
||||
|
||||
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
|
||||
@@ -6,6 +6,8 @@
|
||||
# Currently either Vx or Unix
|
||||
BUILD_TYPE = Unix
|
||||
|
||||
ARCH_CLASS = hp700
|
||||
|
||||
# Compiler and utility invocation (supply path to compiler here)
|
||||
# (with warning flags built in)
|
||||
# Paths to compilers
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
SHELL=knts
|
||||
|
||||
# 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=9
|
||||
|
||||
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.
|
||||
#
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -76,10 +76,11 @@ 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++
|
||||
#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)
|
||||
|
||||
@@ -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,29 +374,41 @@ 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
|
||||
@$(RM) y.tab.c y.tab.h
|
||||
$(YACC) $(YACCOPT) $<
|
||||
@if [ -f y.tab.c ]; \
|
||||
then \
|
||||
@@ -399,9 +424,9 @@ endif
|
||||
fi
|
||||
|
||||
%.c: ../%.l
|
||||
$(RM) lex.yy.c
|
||||
@$(RM) lex.yy.c
|
||||
$(LEX) $(LEXOPT) $<
|
||||
$(RM) $@
|
||||
@$(RM) $@
|
||||
$(MV) lex.yy.c $@
|
||||
|
||||
#state notation language rule
|
||||
@@ -445,7 +470,6 @@ endif
|
||||
$(MANGEN) -s $(<F)
|
||||
$(MV) $(<F).nr $(<F).1
|
||||
|
||||
|
||||
# Rules for building LIBRARY with LIBSRCS
|
||||
# (which are now LIBNAME, LIBOBJS)
|
||||
#
|
||||
@@ -468,7 +492,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 +501,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 +578,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) $@
|
||||
@@ -154,7 +158,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 +203,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,6 +19,7 @@ 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
|
||||
@@ -35,6 +40,7 @@ makelinks:
|
||||
echo "$$dir not found" ; \
|
||||
fi ; \
|
||||
done
|
||||
endif
|
||||
|
||||
clean::
|
||||
@$(RM) ascf bin vxWorks vxWorks.sym dbd share $(APPDIR)
|
||||
|
||||
@@ -52,14 +52,10 @@ $(crossArchs) :
|
||||
endif
|
||||
|
||||
$(hostDirs) :
|
||||
$(MKDIR) $@
|
||||
echo "T_A=$(subst O.,,$@)" > $@/Makefile
|
||||
echo "include ../Makefile.$(BUILD_TYPE)" >> $@/Makefile
|
||||
$(PERL) $(EPICS_BASE)/config/makeMakefile.pl $@ $(BUILD_TYPE)
|
||||
|
||||
$(crossDirs) :
|
||||
$(MKDIR) $@
|
||||
echo "T_A=$(subst O.,,$@)" > $@/Makefile
|
||||
echo "include ../Makefile.Vx" >> $@/Makefile
|
||||
$(PERL) $(EPICS_BASE)/config/makeMakefile.pl $@ Vx
|
||||
|
||||
#
|
||||
# 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
|
||||
$
|
||||
$! ************************************************************
|
||||
|
||||
|
||||
|
||||
692
src/ca/access.c
692
src/ca/access.c
File diff suppressed because it is too large
Load Diff
133
src/ca/acctst.c
133
src/ca/acctst.c
@@ -7,6 +7,12 @@ static char *sccsId = "@(#) $Id$";
|
||||
|
||||
/*
|
||||
* $Log$
|
||||
* 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 +67,7 @@ static char *sccsId = "@(#) $Id$";
|
||||
/*
|
||||
* CA
|
||||
*/
|
||||
#include <cadef.h>
|
||||
#include "cadef.h"
|
||||
|
||||
#define EVENT_ROUTINE null_event
|
||||
#define CONN_ROUTINE conn
|
||||
@@ -332,7 +338,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 +349,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 +405,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 +459,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 +496,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 +548,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 +942,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);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -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,71 @@ 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 (cacRingBufferReadSize(&piiu->send, FALSE)>0) {
|
||||
maxfd = max (maxfd,piiu->sock_chan);
|
||||
if (flags&CA_DO_SENDS || piiu->pushPending) {
|
||||
if (piiu->state==iiu_connecting) {
|
||||
FD_SET (piiu->sock_chan, &pfdi->writeMask);
|
||||
ioPending = TRUE;
|
||||
}
|
||||
else {
|
||||
if (cacRingBufferReadSize(&piiu->send, FALSE)>0) {
|
||||
maxfd = max (maxfd,piiu->sock_chan);
|
||||
FD_SET (piiu->sock_chan, &pfdi->writeMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 +182,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
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iocinf.h>
|
||||
#include "iocinf.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
182
src/ca/cadef.h
182
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 */
|
||||
};
|
||||
|
||||
@@ -202,7 +199,7 @@ struct channel_in_use{
|
||||
unsigned sid; /* server id */
|
||||
struct dbAddr *paddr; /* database address */
|
||||
} id;
|
||||
READONLY void *puser; /* user available area */
|
||||
const void *puser; /* user available area */
|
||||
enum channel_state state; /* connected/ disconnected etc */
|
||||
caar ar; /* access rights */
|
||||
|
||||
@@ -218,15 +215,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 +234,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 +249,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 +264,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 +274,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 +310,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 +359,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 +378,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 +395,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 +407,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 +421,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 +433,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 +481,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 +506,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 +560,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 +619,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 +679,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 +703,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 +769,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 +781,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 +789,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 +798,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 +812,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 +839,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 +861,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 +873,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 +912,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 +921,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 +932,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 +943,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 +964,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 +985,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 +1001,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 +1011,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 +1021,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 +1033,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 +1054,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;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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 ()
|
||||
|
||||
618
src/ca/conn.c
618
src/ca/conn.c
@@ -30,6 +30,9 @@
|
||||
/* (dont send all chans in a block) */
|
||||
/* */
|
||||
/* $Log$
|
||||
* 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 +66,23 @@ LOCAL void logRetryInterval(char *pFN, unsigned lineno);
|
||||
#define LOGRETRYINTERVAL
|
||||
#endif
|
||||
|
||||
LOCAL void retrySearchRequest(int silent);
|
||||
LOCAL void retrySearchRequest();
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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 +102,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 +182,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,36 +191,224 @@ 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;
|
||||
/*
|
||||
* 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 (delay <= 0.0 && ca_static->ca_search_retry < MAXCONNTRIES) {
|
||||
retrySearchRequest ();
|
||||
}
|
||||
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* retrySearchRequest ()
|
||||
*/
|
||||
LOCAL void retrySearchRequest ()
|
||||
{
|
||||
ciu chan;
|
||||
ciu firstChan;
|
||||
int status;
|
||||
unsigned nSent=0u;
|
||||
|
||||
if (!piiuCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* the retry sequence number
|
||||
* (increments once all channels have received this
|
||||
* number of tries)
|
||||
* check to see if there is nothing to do here
|
||||
*/
|
||||
if (ca_static->ca_search_retry >= MAXCONNTRIES) {
|
||||
ca_static->ca_manage_conn_active = FALSE;
|
||||
return;
|
||||
if (ellCount(&piiuCast->chidlist)==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
retrySearchRequest (silent);
|
||||
LOCK;
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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)) ) {
|
||||
/*
|
||||
* double UDP frames per try if we have a good score
|
||||
*/
|
||||
if (ca_static->ca_frames_per_try < (UINT_MAX/2u) ) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* a successful search_msg() sends channel to
|
||||
* the end of the list
|
||||
*/
|
||||
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);
|
||||
}
|
||||
else {
|
||||
ca_static->ca_search_responses=0u;
|
||||
}
|
||||
ca_static->ca_search_tries = 0u;
|
||||
ca_static->ca_min_retry = UINT_MAX;
|
||||
}
|
||||
|
||||
/*
|
||||
* this moves the channel to the end of the
|
||||
* list (if successful)
|
||||
*/
|
||||
status = search_msg (chan, DONTREPLY);
|
||||
if (status != ECA_NORMAL) {
|
||||
nSent++;
|
||||
|
||||
/*
|
||||
* flush out the search request buffer
|
||||
*/
|
||||
(*piiuCast->sendBytes)(piiuCast);
|
||||
|
||||
/*
|
||||
* try again
|
||||
*/
|
||||
status = search_msg (chan, DONTREPLY);
|
||||
if (status != ECA_NORMAL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nSent>=ca_static->ca_frames_per_try) {
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
* cacClrSearchCounters()
|
||||
* (reset broadcasted search counters)
|
||||
*/
|
||||
void cacClrSearchCounters()
|
||||
{
|
||||
ca_static->ca_search_responses = 0u;
|
||||
ca_static->ca_search_tries = 0;
|
||||
ca_static->ca_frames_per_try = TRIESPERFRAME;
|
||||
ca_static->ca_conn_next_retry = ca_static->currentTime;
|
||||
cacSetRetryInterval(0u);
|
||||
}
|
||||
|
||||
/*
|
||||
* cacSetRetryInterval()
|
||||
* (sets the interval between search tries)
|
||||
*/
|
||||
void cacSetRetryInterval(unsigned retryNo)
|
||||
{
|
||||
long idelay;
|
||||
ca_real delay;
|
||||
|
||||
/*
|
||||
* NOOP if no change
|
||||
*/
|
||||
if (ca_static->ca_search_retry == retryNo) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* set the retry interval
|
||||
*/
|
||||
ca_static->ca_search_retry = retryNo;
|
||||
assert(ca_static->ca_search_retry < CHAR_BIT*sizeof(idelay));
|
||||
idelay = 1;
|
||||
idelay = idelay << ca_static->ca_search_retry;
|
||||
@@ -226,104 +418,6 @@ void manage_conn(int silent)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* retrySearchRequest ()
|
||||
*/
|
||||
LOCAL void retrySearchRequest (int silent)
|
||||
{
|
||||
ELLLIST channelsSent;
|
||||
ciu chix;
|
||||
unsigned min_retry_num;
|
||||
unsigned retry_cnt = 0;
|
||||
unsigned retry_cnt_no_handler = 0;
|
||||
int status;
|
||||
|
||||
if (!piiuCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
ellInit (&channelsSent);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if we saw the entire list
|
||||
*/
|
||||
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++;
|
||||
}
|
||||
|
||||
/*
|
||||
* jump to the minimum retry number
|
||||
*/
|
||||
if (ca_static->ca_search_retry<min_retry_num) {
|
||||
ca_static->ca_search_retry = min_retry_num;
|
||||
ca_static->ca_search_responses = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
ellConcat (&piiuCast->chidlist, &channelsSent);
|
||||
|
||||
/*
|
||||
* LOCK around use of the sprintf buffer
|
||||
*/
|
||||
if (retry_cnt) {
|
||||
if (!silent && retry_cnt_no_handler) {
|
||||
sprintf (
|
||||
sprintf_buf,
|
||||
"%d channels outstanding",
|
||||
retry_cnt);
|
||||
genLocalExcep (ECA_CHIDRETRY, sprintf_buf);
|
||||
}
|
||||
}
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
@@ -368,12 +462,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 +471,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->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->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->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 +636,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,7 +658,7 @@ 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 in_addr *pnet_addr, unsigned sawBeacon)
|
||||
{
|
||||
bhe *pBHE;
|
||||
unsigned index;
|
||||
@@ -534,7 +679,7 @@ 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\n", pnet_addr->s_addr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -543,10 +688,29 @@ bhe *createBeaconHashEntry(const struct in_addr *pnet_addr)
|
||||
pBHE->inetAddr = *pnet_addr;
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -643,3 +807,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,6 +91,9 @@ 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[]
|
||||
=
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
449
src/ca/iocinf.c
449
src/ca/iocinf.c
@@ -47,6 +47,15 @@
|
||||
/* address in use so that test works on UNIX */
|
||||
/* kernels that support multicast */
|
||||
/* $Log$
|
||||
* 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 +109,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);
|
||||
|
||||
|
||||
@@ -134,7 +147,7 @@ struct ioc_in_use **ppiiu
|
||||
LOCK;
|
||||
pBHE = lookupBeaconInetAddr(pnet_addr);
|
||||
if(!pBHE){
|
||||
pBHE = createBeaconHashEntry(pnet_addr);
|
||||
pBHE = createBeaconHashEntry(pnet_addr, FALSE);
|
||||
if(!pBHE){
|
||||
UNLOCK;
|
||||
return ECA_ALLOCMEM;
|
||||
@@ -142,11 +155,11 @@ 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;
|
||||
}
|
||||
}
|
||||
@@ -182,9 +195,6 @@ int net_proto
|
||||
int status;
|
||||
SOCKET sock;
|
||||
int true = TRUE;
|
||||
#if 0
|
||||
struct sockaddr_in saddr;
|
||||
#endif
|
||||
caAddrNode *pNode;
|
||||
|
||||
LOCK;
|
||||
@@ -207,6 +217,13 @@ 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:
|
||||
@@ -214,7 +231,7 @@ int net_proto
|
||||
assert(pnet_addr);
|
||||
pNode = (caAddrNode *)calloc(1,sizeof(*pNode));
|
||||
if(!pNode){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
UNLOCK;
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -224,7 +241,7 @@ int net_proto
|
||||
pNode->destAddr.in.sin_port = htons (port);
|
||||
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 +250,7 @@ int net_proto
|
||||
SOCK_STREAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == INVALID_SOCKET){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
UNLOCK;
|
||||
return ECA_SOCK;
|
||||
@@ -251,6 +269,7 @@ int net_proto
|
||||
(char *)&true,
|
||||
sizeof(true));
|
||||
if(status < 0){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
@@ -273,6 +292,7 @@ int net_proto
|
||||
(char *)&true,
|
||||
sizeof true);
|
||||
if(status < 0){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
status = socket_close(sock);
|
||||
if(status<0){
|
||||
@@ -299,7 +319,6 @@ int net_proto
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CA_SET_TCP_BUFFER_SIZES
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
@@ -310,9 +329,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,9 +343,10 @@ int net_proto
|
||||
sock,
|
||||
SOL_SOCKET,
|
||||
SO_RCVBUF,
|
||||
&i,
|
||||
(char *)&i,
|
||||
sizeof(i));
|
||||
if(status < 0){
|
||||
free(pNode);
|
||||
free(piiu);
|
||||
socket_close(sock);
|
||||
UNLOCK;
|
||||
@@ -341,43 +362,40 @@ int net_proto
|
||||
(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->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;
|
||||
|
||||
@@ -422,6 +440,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;
|
||||
@@ -454,10 +496,19 @@ int net_proto
|
||||
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:
|
||||
@@ -470,21 +521,8 @@ int net_proto
|
||||
return ECA_INTERNAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
*/
|
||||
status = socket_ioctl(
|
||||
piiu->sock_chan,
|
||||
FIONBIO,
|
||||
&true);
|
||||
if(status<0){
|
||||
ca_printf(
|
||||
"Error setting non-blocking io: %s\n",
|
||||
strerror(SOCKERRNO));
|
||||
}
|
||||
|
||||
if(fd_register_func){
|
||||
if (fd_register_func) {
|
||||
LOCKEVENTS;
|
||||
(*fd_register_func)((void *)fd_register_arg, sock, TRUE);
|
||||
UNLOCKEVENTS;
|
||||
@@ -495,7 +533,6 @@ int net_proto
|
||||
*/
|
||||
ellAdd(&iiuList, &piiu->node);
|
||||
|
||||
piiu->conn_up = TRUE;
|
||||
*ppiiu = piiu;
|
||||
|
||||
UNLOCK;
|
||||
@@ -503,6 +540,129 @@ int net_proto
|
||||
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
|
||||
*/
|
||||
status = socket_ioctl(
|
||||
piiu->sock_chan,
|
||||
FIONBIO,
|
||||
&true);
|
||||
if(status<0){
|
||||
ca_printf(
|
||||
"CAC: failed to set non-blocking because \"%s\"\n",
|
||||
strerror(SOCKERRNO));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
) {
|
||||
ca_printf(
|
||||
"CAC: duplicate connect err %d=\"%s\"\n",
|
||||
errnoCpy, strerror(errnoCpy));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* put the iiu into the connected state
|
||||
*/
|
||||
piiu->state = iiu_connected;
|
||||
|
||||
piiu->sendBytes = cac_tcp_send_msg_piiu;
|
||||
|
||||
cac_gettimeval (&piiu->timeAtLastRecv);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* caSetupBCastAddrList()
|
||||
@@ -510,7 +670,7 @@ int net_proto
|
||||
void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port)
|
||||
{
|
||||
char *pstr;
|
||||
ENV_PARAM yesno;
|
||||
char yesno[32u];
|
||||
int yes;
|
||||
|
||||
/*
|
||||
@@ -526,8 +686,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 +744,7 @@ void notify_ca_repeater()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!piiuCast->conn_up) {
|
||||
if (piiuCast->state!=iiu_connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -676,7 +836,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 +893,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 +912,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 +933,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 +959,7 @@ LOCAL void cac_tcp_send_msg_piiu(struct ioc_in_use *piiu)
|
||||
}
|
||||
|
||||
CAC_RING_BUFFER_READ_ADVANCE(&piiu->send, status);
|
||||
|
||||
}
|
||||
|
||||
if (status==0) {
|
||||
@@ -822,34 +990,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 +1002,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 +1038,7 @@ void ca_process_input_queue()
|
||||
piiu;
|
||||
piiu=(IIU *)piiu->node.next){
|
||||
|
||||
if(!piiu->conn_up){
|
||||
if(piiu->state!=iiu_connected){
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -906,8 +1046,6 @@ void ca_process_input_queue()
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
cac_flush_internal();
|
||||
}
|
||||
|
||||
|
||||
@@ -921,7 +1059,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 +1171,6 @@ LOCAL void ca_process_tcp(struct ioc_in_use *piiu)
|
||||
post_msg_active = FALSE;
|
||||
UNLOCK;
|
||||
|
||||
flow_control(piiu);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1051,7 +1187,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 +1304,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,
|
||||
@@ -1311,19 +1448,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 +1490,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 +1596,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 +1630,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 +1658,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 +1684,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 +1731,7 @@ unsigned long cacRingBufferWriteSize(struct ca_buffer *pBuf, int contiguous)
|
||||
}
|
||||
}
|
||||
else{
|
||||
count = 0;
|
||||
count = 0u;
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -1653,21 +1781,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 +1805,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 +1837,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 +1891,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 +1940,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 +1986,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 +2017,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;
|
||||
|
||||
|
||||
118
src/ca/iocinf.h
118
src/ca/iocinf.h
@@ -32,6 +32,18 @@
|
||||
/************************************************************************/
|
||||
|
||||
/* $Log$
|
||||
* 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 +139,6 @@ HDRVERSIONID(iocinfh, "$Id$")
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
/*
|
||||
* OS dependent includes
|
||||
*/
|
||||
@@ -138,13 +148,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 +238,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 +265,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 +273,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.
|
||||
@@ -301,7 +320,16 @@ typedef struct caclient_put_notify{
|
||||
}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 +346,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 +366,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 +414,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
|
||||
*/
|
||||
@@ -424,15 +448,17 @@ 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;
|
||||
|
||||
/*
|
||||
@@ -460,13 +486,10 @@ typedef struct {
|
||||
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 +498,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,9 +512,20 @@ 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 long ca_search_responses; /* num valid search resp within seq # */
|
||||
unsigned long 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;
|
||||
char ca_sprintf_buf[256];
|
||||
@@ -509,11 +541,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;
|
||||
@@ -572,18 +604,19 @@ 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 manage_conn();
|
||||
void mark_server_available(const struct in_addr *pnet_addr);
|
||||
void flow_control(struct ioc_in_use *piiu);
|
||||
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);
|
||||
@@ -648,12 +681,11 @@ 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);
|
||||
bhe *createBeaconHashEntry(const struct in_addr *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);
|
||||
@@ -677,6 +709,12 @@ 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 cacClrSearchCounters();
|
||||
void cacSetRetryInterval(unsigned retryNo);
|
||||
void addToChanList(ciu chan, IIU *piiu);
|
||||
void removeFromChanList(ciu chan);
|
||||
|
||||
/*
|
||||
* !!KLUDGE!!
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef _NET_CONVERT_H
|
||||
#define _NET_CONVERT_H
|
||||
|
||||
#include <db_access.h>
|
||||
#include "db_access.h"
|
||||
|
||||
/*
|
||||
* Here are the definitions for architecture dependent byte ordering
|
||||
@@ -85,7 +85,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[];
|
||||
extern CACVRTFUNC *cac_dbr_cvrt[LAST_BUFFER_TYPE+1];
|
||||
#endif
|
||||
|
||||
|
||||
@@ -100,11 +100,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
|
||||
@@ -120,19 +124,19 @@ extern CACVRTFUNC *cac_dbr_cvrt[];
|
||||
# ifndef ntohl
|
||||
# define ntohl(LONG)\
|
||||
(\
|
||||
((LONG) & 0xff000000) >> 24 |\
|
||||
((LONG) & 0x000000ff) << 24 |\
|
||||
((LONG) & 0x0000ff00) << 8 |\
|
||||
((LONG) & 0x00ff0000) >> 8\
|
||||
((LONG) & (dbr_long_t) 0xff000000) >> 24 |\
|
||||
((LONG) & (dbr_long_t) 0x000000ff) << 24 |\
|
||||
((LONG) & (dbr_long_t) 0x0000ff00) << 8 |\
|
||||
((LONG) & (dbr_long_t) 0x00ff0000) >> 8\
|
||||
)
|
||||
# endif
|
||||
# ifndef htonl
|
||||
# define htonl(LONG)\
|
||||
(\
|
||||
((LONG) & 0x000000ff) << 24 |\
|
||||
((LONG) & 0xff000000) >> 24 |\
|
||||
((LONG) & 0x00ff0000) >> 8 |\
|
||||
((LONG) & 0x0000ff00) << 8\
|
||||
( (dbr_long_t) \
|
||||
(((LONG) & (dbr_long_t) 0x000000ff) << 24 |\
|
||||
((LONG) & (dbr_long_t) 0xff000000) >> 24 |\
|
||||
((LONG) & (dbr_long_t) 0x00ff0000) >> 8 |\
|
||||
((LONG) & (dbr_long_t) 0x0000ff00) << 8 )\
|
||||
)
|
||||
# endif
|
||||
# else
|
||||
|
||||
@@ -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,9 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* 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 +55,6 @@
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
#define _POSIX_C_SOURCE 3 /* for solaris and "cc -Xc" */
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
/*
|
||||
* cac_gettimeval
|
||||
@@ -123,37 +123,9 @@ int cac_add_task_variable(struct ca_static *ca_temp)
|
||||
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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
203
src/ca/service.c
203
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);
|
||||
@@ -728,7 +733,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,16 +788,18 @@ 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;
|
||||
|
||||
if (piiu!=piiuCast) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* ignore broadcast replies for deleted channels
|
||||
*
|
||||
@@ -807,8 +814,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;
|
||||
@@ -825,20 +831,19 @@ const struct in_addr *pnet_addr
|
||||
/*
|
||||
* Ignore duplicate search replies
|
||||
*/
|
||||
if (chpiiu != piiuCast) {
|
||||
if (piiuCast != (IIU *) chan->piiu) {
|
||||
caAddrNode *pNode;
|
||||
IIU *tcpPIIU = (IIU *) chan->piiu;
|
||||
|
||||
pNode = (caAddrNode *) chpiiu->destAddr.node.next;
|
||||
pNode = (caAddrNode *) ellFirst(&tcpPIIU->destAddr);
|
||||
assert(pNode);
|
||||
if (pNode->destAddr.in.sin_addr.s_addr !=
|
||||
pnet_addr->s_addr) {
|
||||
|
||||
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,
|
||||
tcpPIIU->host_name_str,
|
||||
rej);
|
||||
genLocalExcep (ECA_DBLCHNL, sprintf_buf);
|
||||
}
|
||||
@@ -897,30 +902,38 @@ 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
|
||||
*/
|
||||
chan->id.sid = piiu->curMsg.m_cid;
|
||||
issue_claim_channel(allocpiiu, chan);
|
||||
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 +946,54 @@ const struct in_addr *pnet_addr
|
||||
chan->ar.read_access = TRUE;
|
||||
chan->ar.write_access = TRUE;
|
||||
|
||||
UNLOCK;
|
||||
/*
|
||||
* Reset the delay to the next search request if we get
|
||||
* at least one response. This may result in an over
|
||||
* run of the UDP input queue of the server in some
|
||||
* cases (and therefore in redundant search requests)
|
||||
* but it does significantly reduce the connect delays
|
||||
* when 1000's of channels must be connected.
|
||||
*/
|
||||
ca_static->ca_conn_next_retry = ca_static->currentTime;
|
||||
|
||||
v42 = CA_V42(
|
||||
CA_PROTOCOL_VERSION,
|
||||
allocpiiu->minor_version_number);
|
||||
if (!v42) {
|
||||
reconnect_channel(piiu, chan);
|
||||
}
|
||||
/*
|
||||
* 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 +1058,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,9 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* 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 +58,7 @@
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "freeList.h"
|
||||
|
||||
LOCAL void io_complete(struct event_handler_args args);
|
||||
|
||||
@@ -67,8 +71,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;
|
||||
}
|
||||
@@ -99,13 +103,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 +136,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 +172,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 +219,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 +419,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 +458,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 +482,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 +521,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 +543,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 +562,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 +583,8 @@ LOCAL void io_complete(struct event_handler_args args)
|
||||
|
||||
UNLOCK;
|
||||
|
||||
freeListFree(ca_static->ca_sgopFreeListPVT, pcasgop);
|
||||
|
||||
/*
|
||||
* Wake up any tasks pending
|
||||
*
|
||||
|
||||
@@ -29,6 +29,15 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* 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,9 +62,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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);
|
||||
@@ -64,6 +75,7 @@ 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
|
||||
@@ -356,11 +368,13 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
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 +402,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 +412,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);
|
||||
@@ -470,10 +484,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 +556,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 +640,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()
|
||||
@@ -776,7 +805,7 @@ void ca_spawn_repeater()
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
if (status < 0){
|
||||
if (status==ERROR){
|
||||
SEVCHK(ECA_NOREPEATER, NULL);
|
||||
}
|
||||
}
|
||||
@@ -894,14 +923,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,15 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* 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 +56,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 +65,7 @@
|
||||
#include <process.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include <epicsVersion.h>
|
||||
#include "epicsVersion.h"
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
@@ -162,16 +153,6 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
|
||||
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 ();
|
||||
@@ -492,7 +473,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 +481,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 +489,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 +543,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).
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ LIBSRCS += casAsyncXXIO.cc
|
||||
LIBSRCS += casAsyncRdIOI.cc
|
||||
LIBSRCS += casAsyncWtIOI.cc
|
||||
LIBSRCS += casAsyncExIOI.cc
|
||||
LIBSRCS += casAsyncPVCIOI.cc
|
||||
LIBSRCS += casEventSys.cc
|
||||
LIBSRCS += casMonitor.cc
|
||||
LIBSRCS += casMonEvent.cc
|
||||
@@ -58,7 +59,6 @@ LIBSRCS += casIntfIO.cc
|
||||
LIBSRCS += casDGIntfIO.cc
|
||||
LIBSRCS += casDGIO.cc
|
||||
LIBSRCS += casStreamIO.cc
|
||||
LIBSRCS += sigPipeIgnore.c
|
||||
|
||||
LIBRARY := cas
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -102,7 +123,7 @@ osiBool exScanTimer::again() const
|
||||
//
|
||||
const osiTime exScanTimer::delay() const
|
||||
{
|
||||
return pv.getScanRate();
|
||||
return pv.getScanPeriod();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -132,19 +153,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 +181,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) {
|
||||
|
||||
@@ -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,267 @@
|
||||
// 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 pvCreateReturn(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) {
|
||||
pvCreateReturn(S_casApp_noMemory);
|
||||
}
|
||||
return pvCreateReturn(*pPV);
|
||||
}
|
||||
//
|
||||
// Initiate async IO if this is an async PV
|
||||
//
|
||||
else {
|
||||
if (this->simultAsychIOCount>=maxSimultAsyncIO) {
|
||||
return pvCreateReturn(S_casApp_postponeAsyncIO);
|
||||
}
|
||||
|
||||
this->simultAsychIOCount++;
|
||||
|
||||
exAsyncCreateIO *pIO =
|
||||
new exAsyncCreateIO(pvi, *this, ctx);
|
||||
if (pIO) {
|
||||
return pvCreateReturn(S_casApp_asyncCompletion);
|
||||
}
|
||||
else {
|
||||
return pvCreateReturn(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 +275,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 +315,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 +329,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,64 @@ public:
|
||||
// for this class
|
||||
//
|
||||
pvInfo (const pvInfo ©In) :
|
||||
scanRate(copyIn.scanRate), name(copyIn.name),
|
||||
scanPeriod(copyIn.scanPeriod), pName(copyIn.pName),
|
||||
hopr(copyIn.hopr), lopr(copyIn.lopr),
|
||||
ioType(copyIn.ioType), elementCount(copyIn.elementCount)
|
||||
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; }
|
||||
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; }
|
||||
|
||||
void destroy ()
|
||||
{
|
||||
//
|
||||
// always created with new
|
||||
//
|
||||
delete this;
|
||||
}
|
||||
private:
|
||||
pvInfo &info;
|
||||
exServer &cas;
|
||||
};
|
||||
|
||||
//
|
||||
// exScanTimer
|
||||
@@ -107,13 +143,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 +205,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 +252,8 @@ 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 +264,8 @@ 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 +280,46 @@ 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, "inconsistent simultAsychIOCount?\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,56 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
|
||||
#include "exServer.h"
|
||||
#include "gddAppFuncTable.cc"
|
||||
#include "resourceLib.cc"
|
||||
|
||||
//
|
||||
// Sun C++ 4.1 still appears to be lacking support in this area
|
||||
// if the compiler supports explicit instantiation of
|
||||
// template member functions
|
||||
//
|
||||
#if !defined(__SUNPRO_CC)
|
||||
#if defined(EXPL_TEMPL)
|
||||
//
|
||||
// From Stroustrups's "The C++ Programming Language"
|
||||
// Appendix A: r.14.9
|
||||
@@ -22,5 +24,6 @@
|
||||
// member functions into "templInst.o"
|
||||
//
|
||||
template class gddAppFuncTable <exPV>;
|
||||
template class resTable <pvEntry,stringId>;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,14 +3,19 @@
|
||||
// Author: Jeff HIll (LANL)
|
||||
//
|
||||
// $Log$
|
||||
// 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 <exServer.h>
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include "exServer.h"
|
||||
|
||||
//
|
||||
// so we can call this from the vxWorks shell
|
||||
//
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.4 1996/11/02 00:53:53 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.3 1996/09/16 18:23:56 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -41,26 +44,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <server.h>
|
||||
#include <caServerIIL.h> // caServerI in line func
|
||||
#include <dbMapper.h> // ait to dbr types
|
||||
#include <gddAppTable.h> // EPICS application type table
|
||||
#include "server.h"
|
||||
#include "caServerIIL.h" // caServerI in line func
|
||||
#include "dbMapper.h" // ait to dbr types
|
||||
#include "gddAppTable.h" // EPICS application type table
|
||||
|
||||
//
|
||||
// NOTES
|
||||
// .01 All use of member pCAS in this file must first verify
|
||||
// that we successfully created a caServerI in
|
||||
// the constructor
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// caServer::caServer()
|
||||
//
|
||||
caServer::caServer(unsigned pvMaxNameLengthIn, unsigned pvCountEstimateIn,
|
||||
unsigned maxSimultaneousIOIn) :
|
||||
pCAS (new caServerI(*this, pvMaxNameLengthIn,
|
||||
pvCountEstimateIn, maxSimultaneousIOIn)),
|
||||
caServer::caServer(unsigned pvCountEstimateIn) :
|
||||
pCAS (new caServerI(*this, pvCountEstimateIn)),
|
||||
valueEventMask(this->registerEvent("value")),
|
||||
logEventMask(this->registerEvent("log")),
|
||||
alarmEventMask(this->registerEvent("alarm"))
|
||||
@@ -112,7 +107,7 @@ casEventMask caServer::registerEvent (const char *pName)
|
||||
//
|
||||
// caServer::show()
|
||||
//
|
||||
void caServer::show(unsigned level)
|
||||
void caServer::show(unsigned level) const
|
||||
{
|
||||
if (this->pCAS) {
|
||||
this->pCAS->show(level);
|
||||
@@ -149,6 +144,8 @@ unsigned caServer::getDebugLevel ()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casRes::~casRes()
|
||||
//
|
||||
// This must be virtual so that derived destructor will
|
||||
// be run indirectly. Therefore it cannot be inline.
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.6 1996/11/02 00:53:54 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.5 1996/09/16 18:23:56 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -50,8 +53,8 @@
|
||||
#define CAS_VERSION_GLOBAL
|
||||
|
||||
#define caServerGlobal
|
||||
#include <server.h>
|
||||
#include <casCtxIL.h> // casCtx in line func
|
||||
#include "server.h"
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
|
||||
static const osiTime CAServerMaxBeaconPeriod (5.0 /* sec */);
|
||||
static const osiTime CAServerMinBeaconPeriod (1.0e-3 /* sec */);
|
||||
@@ -60,9 +63,8 @@ static const osiTime CAServerMinBeaconPeriod (1.0e-3 /* sec */);
|
||||
//
|
||||
// caServerI::show()
|
||||
//
|
||||
void caServerI::show (unsigned level)
|
||||
void caServerI::show (unsigned level) const
|
||||
{
|
||||
casStrmClient *pClient;
|
||||
int bytes_reserved;
|
||||
|
||||
printf( "Channel Access Server Status V%d.%d\n",
|
||||
@@ -71,16 +73,19 @@ void caServerI::show (unsigned level)
|
||||
this->osiMutex::show(level);
|
||||
|
||||
this->osiLock();
|
||||
tsDLFwdIter<casStrmClient> iterCl(this->clientList);
|
||||
while ( (pClient = iterCl.next()) ) {
|
||||
pClient->show(level);
|
||||
const tsDLIterBD<casStrmClient> eolSC;
|
||||
tsDLIterBD<casStrmClient> iterCl(this->clientList.first());
|
||||
while ( iterCl!=eolSC ) {
|
||||
iterCl->show(level);
|
||||
++iterCl;
|
||||
}
|
||||
this->dgClient.show(level);
|
||||
|
||||
casIntfOS *pIF;
|
||||
tsDLFwdIter<casIntfOS> iterIF(this->intfList);
|
||||
while ( (pIF = iterIF.next()) ) {
|
||||
pIF->show(level);
|
||||
const tsDLIterBD<casIntfOS> eolIOS;
|
||||
tsDLIterBD<casIntfOS> iterIF(this->intfList.first());
|
||||
while ( iterIF!=eolIOS ) {
|
||||
iterIF->show(level);
|
||||
++iterIF;
|
||||
}
|
||||
|
||||
this->osiUnlock();
|
||||
@@ -113,11 +118,6 @@ void caServerI::show (unsigned level)
|
||||
this->osiLock();
|
||||
this->uintResTable<casRes>::show(level);
|
||||
this->osiUnlock();
|
||||
printf(
|
||||
"The server's character string resource id conversion table:\n");
|
||||
this->osiLock();
|
||||
this->stringResTbl.show(level);
|
||||
this->osiUnlock();
|
||||
}
|
||||
|
||||
// @@@@@@ caPrintAddrList(&destAddr);
|
||||
@@ -129,8 +129,7 @@ void caServerI::show (unsigned level)
|
||||
//
|
||||
// caServerI::caServerI()
|
||||
//
|
||||
caServerI::caServerI (caServer &tool, unsigned maxNameLength,
|
||||
unsigned nPV, unsigned maxSimultIO) :
|
||||
caServerI::caServerI (caServer &tool, unsigned nPV) :
|
||||
caServerOS(*this),
|
||||
casEventRegistry(* (osiMutex *) this),
|
||||
dgClient(*this),
|
||||
@@ -141,18 +140,14 @@ caServerI::caServerI (caServer &tool, unsigned maxNameLength,
|
||||
//
|
||||
beaconPeriod(CAServerMinBeaconPeriod),
|
||||
adapter(tool),
|
||||
pvCount(0u),
|
||||
debugLevel(0u),
|
||||
nExistTestInProg(0u),
|
||||
pvMaxNameLength(maxNameLength),
|
||||
pvCountEstimate(nPV<100u?100u:nPV),
|
||||
maxSimultaneousIO(maxSimultIO),
|
||||
haveBeenInitialized(FALSE)
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
assert(&adapter);
|
||||
ctx.setServer(this);
|
||||
//ctx.setServer(this);
|
||||
|
||||
status = this->init();
|
||||
if (status) {
|
||||
@@ -200,21 +195,12 @@ caStatus caServerI::init()
|
||||
//
|
||||
// hash table size may need adjustment here?
|
||||
//
|
||||
resLibStatus = this->uintResTable<casRes>::init(this->pvCountEstimate*8u);
|
||||
resLibStatus = this->uintResTable<casRes>::init(this->pvCountEstimate*2u);
|
||||
if (resLibStatus) {
|
||||
ca_printf("CAS: integer resource id table init failed\n");
|
||||
return S_cas_noMemory;
|
||||
}
|
||||
|
||||
//
|
||||
// hash table size may need adjustment here?
|
||||
//
|
||||
resLibStatus = this->stringResTbl.init(this->pvCountEstimate*2u);
|
||||
if (resLibStatus) {
|
||||
ca_printf("CAS: string resource id table init failed\n");
|
||||
return S_cas_noMemory;
|
||||
}
|
||||
|
||||
this->haveBeenInitialized = TRUE;
|
||||
return S_cas_success;
|
||||
}
|
||||
@@ -232,13 +218,18 @@ caServerI::~caServerI()
|
||||
//
|
||||
// delete all clients
|
||||
//
|
||||
casClient *pClient;
|
||||
tsDLFwdIter<casStrmClient> iter(this->clientList);
|
||||
pClient = iter.next();
|
||||
while (pClient) {
|
||||
casClient *pNextClient = iter.next();
|
||||
delete pClient;
|
||||
pClient = pNextClient;
|
||||
tsDLIterBD<casStrmClient> iter(this->clientList.first());
|
||||
tsDLIterBD<casStrmClient> eol;
|
||||
tsDLIterBD<casStrmClient> tmp;
|
||||
while ( iter!=eol ) {
|
||||
tmp = iter;
|
||||
++tmp;
|
||||
//
|
||||
// destructor takes client out of list
|
||||
//
|
||||
casStrmClient *pC = iter;
|
||||
delete pC;
|
||||
iter = tmp;
|
||||
}
|
||||
|
||||
casIntfOS *pIF;
|
||||
@@ -247,11 +238,6 @@ caServerI::~caServerI()
|
||||
}
|
||||
|
||||
this->osiUnlock();
|
||||
|
||||
//
|
||||
// verify that we didnt leak a PV
|
||||
//
|
||||
assert (this->pvCount==0u);
|
||||
}
|
||||
|
||||
|
||||
@@ -380,8 +366,6 @@ caStatus caServerI::addAddr(const caAddr &caAddr, int autoBeaconAddr,
|
||||
//
|
||||
void caServerI::sendBeacon()
|
||||
{
|
||||
casIntfOS *pIntf;
|
||||
|
||||
//
|
||||
// send a broadcast beacon over each configured
|
||||
// interface unless EPICS_CA_AUTO_ADDR_LIST specifies
|
||||
@@ -389,9 +373,10 @@ void caServerI::sendBeacon()
|
||||
// addresses.
|
||||
//
|
||||
this->osiLock();
|
||||
tsDLFwdIter<casIntfOS> iter(this->intfList);
|
||||
while ( (pIntf = iter.next()) ) {
|
||||
pIntf->requestBeacon();
|
||||
tsDLIterBD<casIntfOS> iter(this->intfList.first());
|
||||
while ( iter ) {
|
||||
iter->requestBeacon();
|
||||
iter++;
|
||||
}
|
||||
this->osiUnlock();
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.3 1996/11/02 00:53:56 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.2 1996/09/16 18:23:57 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -93,83 +96,13 @@ inline casChannelI *caServerI::resIdToChannel(const caResId &id)
|
||||
return (casChannelI *) pRes;
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::pvExistTestPossible()
|
||||
//
|
||||
inline aitBool caServerI::pvExistTestPossible()
|
||||
{
|
||||
if (this->nExistTestInProg < this->maxSimultaneousIO) {
|
||||
return aitTrue;
|
||||
}
|
||||
return aitFalse;
|
||||
}
|
||||
|
||||
//
|
||||
// find the channel associated with a resource id
|
||||
//
|
||||
inline pvExistReturn caServerI::pvExistTest(
|
||||
inline casPVExistReturn caServerI::pvExistTest(
|
||||
const casCtx &ctxIn, const char *pPVName)
|
||||
{
|
||||
this->osiLock();
|
||||
if (pvExistTestPossible()) {
|
||||
this->nExistTestInProg++;
|
||||
osiUnlock();
|
||||
return (*this)->pvExistTest(ctxIn, pPVName);
|
||||
}
|
||||
else {
|
||||
osiUnlock();
|
||||
return pvExistReturn(S_cas_ioBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::pvExistTestCompletion()
|
||||
//
|
||||
inline void caServerI::pvExistTestCompletion()
|
||||
{
|
||||
this->osiLock();
|
||||
this->nExistTestInProg--;
|
||||
this->osiUnlock();
|
||||
this->ioBlockedList::signal();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// install a PV into the server
|
||||
//
|
||||
inline void caServerI::installPV (casPVI &pv)
|
||||
{
|
||||
int resLibStatus;
|
||||
|
||||
this->osiLock ();
|
||||
this->pvCount++;
|
||||
resLibStatus = this->stringResTbl.add (pv);
|
||||
this->osiUnlock ();
|
||||
assert (resLibStatus==0);
|
||||
}
|
||||
|
||||
//
|
||||
// remove PV from the server
|
||||
//
|
||||
inline void caServerI::removePV(casPVI &pv)
|
||||
{
|
||||
casPVI *pPV;
|
||||
|
||||
this->osiLock();
|
||||
casVerify (this->pvCount>=1u);
|
||||
this->pvCount--;
|
||||
pPV = this->stringResTbl.remove (pv);
|
||||
this->osiUnlock();
|
||||
casVerify (pPV!=0);
|
||||
casVerify (pPV==&pv);
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::getPVMaxNameLength()
|
||||
//
|
||||
inline unsigned caServerI::getPVMaxNameLength() const
|
||||
{
|
||||
return this->pvMaxNameLength;
|
||||
return casPVExistReturn((*this)->pvExistTest(ctxIn, pPVName));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.2 1996/11/06 22:15:53 jhill
|
||||
* allow monitor init read to using rd async io
|
||||
*
|
||||
* Revision 1.1 1996/11/02 01:01:02 jhill
|
||||
* installed
|
||||
*
|
||||
@@ -37,12 +40,12 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include <casAsyncIOIIL.h> // casAsyncIOI in line func
|
||||
#include <casChannelIIL.h> // casChannelI in line func
|
||||
#include <casOpaqueAddrIL.h> // casOpaqueAddr in line func
|
||||
#include <casCtxIL.h> // casCtx in line func
|
||||
#include <casCoreClientIL.h> // casCoreClient in line func
|
||||
#include "server.h"
|
||||
#include "casAsyncIOIIL.h" // casAsyncIOI in line func
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casOpaqueAddrIL.h" // casOpaqueAddr in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#include "casCoreClientIL.h" // casCoreClient in line func
|
||||
|
||||
//
|
||||
// casAsyncExIOI::casAsyncExIOI()
|
||||
@@ -69,7 +72,7 @@ casAsyncExIOI::~casAsyncExIOI()
|
||||
//
|
||||
// casAsyncExIOI::postIOCompletion()
|
||||
//
|
||||
caStatus casAsyncExIOI::postIOCompletion(const pvExistReturn &retValIn)
|
||||
caStatus casAsyncExIOI::postIOCompletion(const pvExistReturn retValIn)
|
||||
{
|
||||
this->retVal = retValIn;
|
||||
return this->postIOCompletionI();
|
||||
@@ -94,10 +97,6 @@ caStatus casAsyncExIOI::cbFuncAsyncIO()
|
||||
this->dgOutAddr.get(), this->msg, this->retVal);
|
||||
break;
|
||||
|
||||
case CA_PROTO_CLAIM_CIU:
|
||||
status = this->client.createChanResponse(this->msg, this->retVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
this->reportInvalidAsynchIO(this->msg.m_cmmd);
|
||||
status = S_cas_internal;
|
||||
|
||||
@@ -29,13 +29,16 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.2 1996/11/02 00:53:57 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.1.1.1 1996/06/20 00:28:14 jhill
|
||||
* ca server installation
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include<server.h>
|
||||
#include"server.h"
|
||||
|
||||
//
|
||||
// This must be virtual so that derived destructor will
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.5 1996/12/13 00:08:35 jhill
|
||||
* dont unlock after destroy
|
||||
*
|
||||
* Revision 1.4 1996/11/02 00:53:58 jhill
|
||||
* many improvements
|
||||
*
|
||||
@@ -36,10 +39,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include <casEventSysIL.h> // casEventSys in line func
|
||||
#include <casAsyncIOIIL.h> // casAsyncIOI in line func
|
||||
#include <casCtxIL.h> // casCtx in line func
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casEventSys in line func
|
||||
#include "casAsyncIOIIL.h" // casAsyncIOI in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
|
||||
//
|
||||
// casAsyncIOI::casAsyncIOI()
|
||||
@@ -52,6 +55,19 @@ casAsyncIOI::casAsyncIOI(casCoreClient &clientIn, casAsyncIO &ioExternalIn) :
|
||||
ioComplete(FALSE),
|
||||
serverDelete(FALSE)
|
||||
{
|
||||
//
|
||||
// catch situation where they create more than one
|
||||
// async IO object per request
|
||||
//
|
||||
if (client.asyncIOFlag) {
|
||||
errMessage(S_cas_badParameter,
|
||||
"- duplicate async IO creation");
|
||||
this->duplicate = TRUE;
|
||||
}
|
||||
else {
|
||||
client.asyncIOFlag = TRUE;
|
||||
this->duplicate = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -165,6 +181,18 @@ caStatus casAsyncIOI::postIOCompletionI()
|
||||
{
|
||||
this->lock();
|
||||
|
||||
if (this->duplicate) {
|
||||
errMessage(S_cas_badParameter,
|
||||
"- duplicate async IO");
|
||||
//
|
||||
// dont use "this" after potentially destroying the
|
||||
// object here
|
||||
//
|
||||
this->serverDelete = TRUE;
|
||||
(*this)->destroy();
|
||||
return S_cas_redundantPost;
|
||||
}
|
||||
|
||||
//
|
||||
// verify that they dont post completion more than once
|
||||
//
|
||||
@@ -194,7 +222,7 @@ caStatus casAsyncIOI::postIOCompletionI()
|
||||
// casAsyncIOI::getCAS()
|
||||
// (not inline because this is used by the interface class)
|
||||
//
|
||||
caServer *casAsyncIOI::getCAS()
|
||||
caServer *casAsyncIOI::getCAS() const
|
||||
{
|
||||
return this->client.getCAS().getAdapter();
|
||||
}
|
||||
@@ -215,13 +243,13 @@ int casAsyncIOI::readOP()
|
||||
//
|
||||
void casAsyncIOI::destroyIfReadOP()
|
||||
{
|
||||
casCoreClient &client = this->client;
|
||||
casCoreClient &clientCopy = this->client;
|
||||
|
||||
//
|
||||
// client lock used because this object's
|
||||
// lock may be destroyed
|
||||
//
|
||||
client.osiLock();
|
||||
clientCopy.osiLock();
|
||||
|
||||
if (this->readOP()) {
|
||||
this->serverDelete = TRUE;
|
||||
@@ -232,7 +260,8 @@ void casAsyncIOI::destroyIfReadOP()
|
||||
// NO REF TO THIS OBJECT BELOW HERE
|
||||
// BECAUSE OF THE DELETE ABOVE
|
||||
//
|
||||
client.osiUnlock();
|
||||
|
||||
clientCopy.osiUnlock();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
101
src/cas/generic/casAsyncPVCIOI.cc
Normal file
101
src/cas/generic/casAsyncPVCIOI.cc
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.2 1996/11/06 22:15:53 jhill
|
||||
* allow monitor init read to using rd async io
|
||||
*
|
||||
* Revision 1.1 1996/11/02 01:01:02 jhill
|
||||
* installed
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "server.h"
|
||||
#include "casAsyncIOIIL.h" // casAsyncIOI in line func
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casOpaqueAddrIL.h" // casOpaqueAddr in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#include "casCoreClientIL.h" // casCoreClient in line func
|
||||
|
||||
//
|
||||
// casAsyncPVCIOI::casAsyncPVCIOI()
|
||||
//
|
||||
casAsyncPVCIOI::casAsyncPVCIOI(const casCtx &ctx,
|
||||
casAsyncPVCreateIO &ioIn) :
|
||||
casAsyncIOI(*ctx.getClient(), ioIn),
|
||||
msg(*ctx.getMsg())
|
||||
{
|
||||
assert (&this->msg);
|
||||
this->client.installAsyncIO(*this);
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVCIOI::~casAsyncPVCIOI()
|
||||
//
|
||||
casAsyncPVCIOI::~casAsyncPVCIOI()
|
||||
{
|
||||
this->client.removeAsyncIO(*this);
|
||||
}
|
||||
|
||||
//
|
||||
// casAsyncPVCIOI::postIOCompletion()
|
||||
//
|
||||
caStatus casAsyncPVCIOI::postIOCompletion(const pvCreateReturn &retValIn)
|
||||
{
|
||||
this->retVal = retValIn;
|
||||
return this->postIOCompletionI();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// casAsyncPVCIOI::cbFuncAsyncIO()
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
//
|
||||
caStatus casAsyncPVCIOI::cbFuncAsyncIO()
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
switch (this->msg.m_cmmd) {
|
||||
case CA_PROTO_CLAIM_CIU:
|
||||
status = this->client.createChanResponse(this->msg, this->retVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
this->reportInvalidAsynchIO(this->msg.m_cmmd);
|
||||
status = S_cas_internal;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.2 1996/11/06 22:15:54 jhill
|
||||
* allow monitor init read to using rd async io
|
||||
*
|
||||
* Revision 1.1 1996/11/02 01:01:03 jhill
|
||||
* installed
|
||||
*
|
||||
@@ -45,10 +48,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include <casAsyncIOIIL.h> // casAsyncIOI in line func
|
||||
#include <casChannelIIL.h> // casChannelI in line func
|
||||
#include <casCtxIL.h> // casCtxI in line func
|
||||
#include "server.h"
|
||||
#include "casAsyncIOIIL.h" // casAsyncIOI in line func
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casCtxIL.h" // casCtxI in line func
|
||||
|
||||
//
|
||||
// casAsyncRdIOI::casAsyncRdIOI()
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.2 1996/11/06 22:15:56 jhill
|
||||
* allow monitor init read to using rd async io
|
||||
*
|
||||
* Revision 1.1 1996/11/02 01:01:04 jhill
|
||||
* installed
|
||||
*
|
||||
@@ -36,10 +39,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include <casAsyncIOIIL.h> // casAsyncIOI in line func
|
||||
#include <casChannelIIL.h> // casChannelI in line func
|
||||
#include <casCtxIL.h> // casCtx in line func
|
||||
#include "server.h"
|
||||
#include "casAsyncIOIIL.h" // casAsyncIOI in line func
|
||||
#include "casChannelIIL.h" // casChannelI in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
|
||||
//
|
||||
// casAsyncWtIOI::casAsyncWtIOI()
|
||||
|
||||
@@ -29,11 +29,14 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.1 1996/11/02 01:01:05 jhill
|
||||
* installed
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <casdef.h>
|
||||
#include "casdef.h"
|
||||
|
||||
//
|
||||
// This must be virtual so that derived destructor will
|
||||
@@ -59,3 +62,11 @@ casAsyncPVExistIO::~casAsyncPVExistIO()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// This must be virtual so that derived destructor will
|
||||
// be run indirectly. Therefore it cannot be inline.
|
||||
//
|
||||
casAsyncPVCreateIO::~casAsyncPVCreateIO()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.2 1996/11/02 00:54:01 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.1.1.1 1996/06/20 00:28:15 jhill
|
||||
* ca server installation
|
||||
*
|
||||
@@ -36,8 +39,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include <casEventSysIL.h> // casEventSys in line func
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casEventSys in line func
|
||||
|
||||
//
|
||||
// casChanDelEv()
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.4 1996/09/04 20:17:34 jhill
|
||||
* use ptr not ref to satisfy MSVISC++
|
||||
*
|
||||
* Revision 1.3 1996/08/13 22:52:31 jhill
|
||||
* changes for MVC++
|
||||
*
|
||||
@@ -42,9 +45,9 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include <casChannelIIL.h> // casChannelI inline func
|
||||
#include <casPVListChanIL.h> // casPVListChan inline func
|
||||
#include "server.h"
|
||||
#include "casChannelIIL.h" // casChannelI inline func
|
||||
#include "casPVListChanIL.h" // casPVListChan inline func
|
||||
|
||||
//
|
||||
// casChannel::casChannel()
|
||||
@@ -73,14 +76,6 @@ casPV *casChannel::getPV()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::postEvent()
|
||||
//
|
||||
void casChannel::postEvent (const casEventMask &select, gdd &event)
|
||||
{
|
||||
this->casChannelI::postEvent(select, event);
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::setOwner()
|
||||
//
|
||||
@@ -92,21 +87,6 @@ void casChannel::setOwner(const char * const /* pUserName */,
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::interestRegister()
|
||||
//
|
||||
caStatus casChannel::interestRegister()
|
||||
{
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::interestDelete()
|
||||
//
|
||||
void casChannel::interestDelete()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::readAccess()
|
||||
//
|
||||
@@ -135,7 +115,7 @@ aitBool casChannel::confirmationRequested() const
|
||||
//
|
||||
// casChannel::show()
|
||||
//
|
||||
void casChannel::show(unsigned level)
|
||||
void casChannel::show(unsigned level) const
|
||||
{
|
||||
if (level>2u) {
|
||||
printf("casChannel: read access = %d\n",
|
||||
@@ -155,4 +135,11 @@ void casChannel::destroy()
|
||||
delete this;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannel::postAccessRightsEvent()
|
||||
//
|
||||
void casChannel::postAccessRightsEvent()
|
||||
{
|
||||
this->casChannelI::postAccessRightsEvent();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.3 1996/11/02 00:54:02 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.2 1996/09/04 20:18:03 jhill
|
||||
* init new chan member
|
||||
*
|
||||
@@ -38,11 +41,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <server.h>
|
||||
#include <casEventSysIL.h> // casEventSys inline func
|
||||
#include <casAsyncIOIIL.h> // casAsyncIOI inline func
|
||||
#include <casPVIIL.h> // casPVI inline func
|
||||
#include <casCtxIL.h> // casCtx inline func
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casEventSys inline func
|
||||
#include "casAsyncIOIIL.h" // casAsyncIOI inline func
|
||||
#include "casPVIIL.h" // casPVI inline func
|
||||
#include "casCtxIL.h" // casCtx inline func
|
||||
|
||||
|
||||
//
|
||||
@@ -52,7 +55,9 @@ casChannelI::casChannelI(const casCtx &ctx, casChannel &chanAdapter) :
|
||||
client(* (casStrmClient *) ctx.getClient()),
|
||||
pv(*ctx.getPV()),
|
||||
chan(chanAdapter),
|
||||
cid(ctx.getMsg()->m_cid)
|
||||
cid(ctx.getMsg()->m_cid),
|
||||
clientDestroyPending(FALSE),
|
||||
accessRightsEvPending(FALSE)
|
||||
{
|
||||
assert(&this->client);
|
||||
assert(&this->pv);
|
||||
@@ -67,8 +72,6 @@ casChannelI::casChannelI(const casCtx &ctx, casChannel &chanAdapter) :
|
||||
//
|
||||
casChannelI::~casChannelI()
|
||||
{
|
||||
casAsyncIOI *pIO;
|
||||
casMonitor *pMonitor;
|
||||
casChanDelEv *pCDEV;
|
||||
caStatus status;
|
||||
|
||||
@@ -77,31 +80,34 @@ casChannelI::~casChannelI()
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
tsDLFwdIter<casAsyncIOI> iterIO(this->ioInProgList);
|
||||
pIO = iterIO.next();
|
||||
while (pIO) {
|
||||
casAsyncIOI *pNextIO;
|
||||
tsDLIterBD<casAsyncIOI> iterAIO(this->ioInProgList.first());
|
||||
const tsDLIterBD<casAsyncIOI> eolAIO;
|
||||
tsDLIterBD<casAsyncIOI> tmpAIO;
|
||||
while ( iterAIO!=eolAIO ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
pNextIO = iterIO.next();
|
||||
pIO->destroy();
|
||||
pIO = pNextIO;
|
||||
tmpAIO = iterAIO;
|
||||
++tmpAIO;
|
||||
iterAIO->destroy();
|
||||
iterAIO = tmpAIO;
|
||||
}
|
||||
|
||||
//
|
||||
// cancel the monitors
|
||||
//
|
||||
tsDLFwdIter<casMonitor> iterMon(this->monitorList);
|
||||
pMonitor = iterMon.next();
|
||||
while (pMonitor) {
|
||||
casMonitor *pNextMon;
|
||||
tsDLIterBD<casMonitor> iterMon(this->monitorList.first());
|
||||
const tsDLIterBD<casMonitor> eolMon;
|
||||
tsDLIterBD<casMonitor> tmpMon;
|
||||
while ( iterMon!=eolMon ) {
|
||||
casMonitor *pMonitor;
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
pNextMon = iterMon.next();
|
||||
pMonitor = tmpMon = iterMon;
|
||||
++tmpMon;
|
||||
delete pMonitor;
|
||||
pMonitor = pNextMon;
|
||||
iterMon = tmpMon;
|
||||
}
|
||||
|
||||
this->client.removeChannel(*this);
|
||||
@@ -112,9 +118,9 @@ casChannelI::~casChannelI()
|
||||
this->pv.deleteSignal();
|
||||
|
||||
//
|
||||
// if its an old client and there is no memory
|
||||
// we disconnect them here (and delete the client)
|
||||
// - therefore dont use member client after this point
|
||||
// If we are not in the process of deleting the client
|
||||
// then inform the client that we have deleted its
|
||||
// channel
|
||||
//
|
||||
if (!this->clientDestroyPending) {
|
||||
pCDEV = new casChanDelEv(this->getCID());
|
||||
@@ -124,10 +130,19 @@ casChannelI::~casChannelI()
|
||||
else {
|
||||
status = this->client.disconnectChan (this->getCID());
|
||||
if (status) {
|
||||
errMessage(status, NULL);
|
||||
if (status == S_cas_disconnect) {
|
||||
this->client.destroy();
|
||||
}
|
||||
//
|
||||
// At this point there is no space in pool
|
||||
// for a tiny object and there is also
|
||||
// no outgoing buffer space in which to place
|
||||
// a message in which we inform the client
|
||||
// that his channel was deleted.
|
||||
//
|
||||
// => disconnect this client via the event
|
||||
// queue because deleting the client here
|
||||
// will result in bugs because no doubt this
|
||||
// could be called by a client member function.
|
||||
//
|
||||
this->client.setDestroyPending();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,23 +156,22 @@ casChannelI::~casChannelI()
|
||||
//
|
||||
void casChannelI::clearOutstandingReads()
|
||||
{
|
||||
casAsyncIOI *pIO;
|
||||
|
||||
this->lock();
|
||||
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
tsDLFwdIter<casAsyncIOI> iterIO(this->ioInProgList);
|
||||
pIO = iterIO.next();
|
||||
while (pIO) {
|
||||
casAsyncIOI *pNextIO;
|
||||
tsDLIterBD<casAsyncIOI> iterIO(this->ioInProgList.first());
|
||||
tsDLIterBD<casAsyncIOI> eolIO;
|
||||
tsDLIterBD<casAsyncIOI> tmp;
|
||||
while (iterIO!=eolIO) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
pNextIO = iterIO.next();
|
||||
pIO->destroyIfReadOP();
|
||||
pIO = pNextIO;
|
||||
tmp = iterIO;
|
||||
++tmp;
|
||||
iterIO->destroyIfReadOP();
|
||||
iterIO = tmp;
|
||||
}
|
||||
|
||||
this->unlock();
|
||||
@@ -169,12 +183,12 @@ void casChannelI::clearOutstandingReads()
|
||||
//
|
||||
void casChannelI::postAllModifiedEvents()
|
||||
{
|
||||
casMonitor *pMon;
|
||||
|
||||
this->lock();
|
||||
tsDLFwdIter<casMonitor> iter(this->monitorList);
|
||||
while ( (pMon=iter.next()) ) {
|
||||
pMon->postIfModified();
|
||||
tsDLIterBD<casMonitor> iter(this->monitorList.first());
|
||||
tsDLIterBD<casMonitor> eol;
|
||||
while ( iter!=eol ) {
|
||||
iter->postIfModified();
|
||||
++iter;
|
||||
}
|
||||
this->unlock();
|
||||
}
|
||||
@@ -183,21 +197,19 @@ void casChannelI::postAllModifiedEvents()
|
||||
//
|
||||
// casChannelI::show()
|
||||
//
|
||||
void casChannelI::show(unsigned level)
|
||||
void casChannelI::show(unsigned level) const
|
||||
{
|
||||
casMonitor *pMon;
|
||||
|
||||
this->lock();
|
||||
tsDLFwdIter<casMonitor> iter(this->monitorList);
|
||||
|
||||
if ( (pMon = iter.next()) ) {
|
||||
tsDLIterBD<casMonitor> iter(this->monitorList.first());
|
||||
tsDLIterBD<casMonitor> eol;
|
||||
if ( iter!=eol ) {
|
||||
printf("List of CA events (monitors) for \"%s\".\n",
|
||||
this->pv.resourceName());
|
||||
this->pv->getName());
|
||||
}
|
||||
|
||||
while (pMon) {
|
||||
pMon->show(level);
|
||||
pMon = iter.next();
|
||||
while ( iter!=eol ) {
|
||||
iter->show(level);
|
||||
++iter;
|
||||
}
|
||||
|
||||
(*this)->show(level);
|
||||
@@ -205,3 +217,38 @@ void casChannelI::show(unsigned level)
|
||||
this->unlock();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// casChannelI::cbFunc()
|
||||
//
|
||||
// access rights event call back
|
||||
//
|
||||
caStatus casChannelI::cbFunc(casEventSys &)
|
||||
{
|
||||
caStatus stat;
|
||||
|
||||
stat = this->client.accessRightsResponse(this);
|
||||
if (stat==S_cas_success) {
|
||||
this->accessRightsEvPending = FALSE;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::destroy()
|
||||
//
|
||||
// call the destroy in the server tool
|
||||
//
|
||||
void casChannelI::destroy()
|
||||
{
|
||||
this->chan.destroy();
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::resourceType()
|
||||
//
|
||||
casResType casChannelI::resourceType() const
|
||||
{
|
||||
return casChanT;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.5 1996/11/02 00:54:03 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.4 1996/09/16 18:23:59 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -48,12 +51,13 @@
|
||||
#ifndef casChannelIIL_h
|
||||
#define casChannelIIL_h
|
||||
|
||||
#include <casCoreClientIL.h>
|
||||
#include "casCoreClientIL.h"
|
||||
#include "casEventSysIL.h"
|
||||
|
||||
//
|
||||
// casChannelI::operator -> ()
|
||||
//
|
||||
inline casChannel * casChannelI::operator -> ()
|
||||
inline casChannel * casChannelI::operator -> () const
|
||||
{
|
||||
return &this->chan;
|
||||
}
|
||||
@@ -61,7 +65,7 @@ inline casChannel * casChannelI::operator -> ()
|
||||
//
|
||||
// casChannelI::lock()
|
||||
//
|
||||
inline void casChannelI::lock()
|
||||
inline void casChannelI::lock() const
|
||||
{
|
||||
this->client.osiLock();
|
||||
}
|
||||
@@ -69,7 +73,7 @@ inline void casChannelI::lock()
|
||||
//
|
||||
// casChannelI::unlock()
|
||||
//
|
||||
inline void casChannelI::unlock()
|
||||
inline void casChannelI::unlock() const
|
||||
{
|
||||
this->client.osiUnlock();
|
||||
}
|
||||
@@ -79,12 +83,12 @@ inline void casChannelI::unlock()
|
||||
//
|
||||
inline void casChannelI::postEvent(const casEventMask &select, gdd &event)
|
||||
{
|
||||
casMonitor *pMon;
|
||||
|
||||
this->lock();
|
||||
tsDLFwdIter<casMonitor> iter(this->monitorList);
|
||||
while ( (pMon = iter.next()) ) {
|
||||
pMon->post(select, event);
|
||||
tsDLIterBD<casMonitor> iter(this->monitorList.first());
|
||||
const tsDLIterBD<casMonitor> eol;
|
||||
while ( iter!=eol ) {
|
||||
iter->post(select, event);
|
||||
++iter;
|
||||
}
|
||||
this->unlock();
|
||||
}
|
||||
@@ -124,14 +128,15 @@ inline void casChannelI::addMonitor(casMonitor &mon)
|
||||
//
|
||||
inline casMonitor *casChannelI::findMonitor(const caResId clientIdIn)
|
||||
{
|
||||
casMonitor *pMon;
|
||||
|
||||
this->lock();
|
||||
tsDLFwdIter<casMonitor> iter(this->monitorList);
|
||||
while ( (pMon = iter.next()) ) {
|
||||
if ( clientIdIn == pMon->getClientId()) {
|
||||
tsDLIterBD<casMonitor> iter(this->monitorList.first());
|
||||
tsDLIterBD<casMonitor> eol;
|
||||
while ( iter!=eol ) {
|
||||
if ( clientIdIn == iter->getClientId()) {
|
||||
casMonitor *pMon = iter;
|
||||
return pMon;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
this->unlock();
|
||||
return NULL;
|
||||
@@ -146,7 +151,7 @@ inline void casChannelI::clientDestroy()
|
||||
(*this)->destroy();
|
||||
}
|
||||
|
||||
#include <casPVIIL.h>
|
||||
#include "casPVIIL.h"
|
||||
|
||||
//
|
||||
// functions that use casPVIIL.h below here
|
||||
@@ -158,7 +163,6 @@ inline void casChannelI::clientDestroy()
|
||||
inline void casChannelI::installAsyncIO(casAsyncIOI &io)
|
||||
{
|
||||
this->lock();
|
||||
this->pv.registerIO();
|
||||
this->ioInProgList.add(io);
|
||||
this->unlock();
|
||||
}
|
||||
@@ -183,6 +187,17 @@ inline const caResId casChannelI::getSID()
|
||||
return this->uintId::getId();
|
||||
}
|
||||
|
||||
//
|
||||
// casChannelI::postAccessRightsEvent()
|
||||
//
|
||||
inline void casChannelI::postAccessRightsEvent()
|
||||
{
|
||||
if (!this->accessRightsEvPending) {
|
||||
this->accessRightsEvPending = TRUE;
|
||||
this->client.addToEventQueue(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // casChannelIIL_h
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.6 1996/12/11 00:58:35 jhill
|
||||
* better diagnostic
|
||||
*
|
||||
* Revision 1.5 1996/11/02 00:54:04 jhill
|
||||
* many improvements
|
||||
*
|
||||
@@ -47,13 +50,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <server.h>
|
||||
#include <casClientIL.h> // inline func for casClient
|
||||
#include <casEventSysIL.h> // inline func for casEventSys
|
||||
#include <casCtxIL.h> // inline func for casCtx
|
||||
#include <inBufIL.h> // inline func for inBuf
|
||||
#include <db_access.h>
|
||||
#include "server.h"
|
||||
#include "casClientIL.h" // inline func for casClient
|
||||
#include "casEventSysIL.h" // inline func for casEventSys
|
||||
#include "casCtxIL.h" // inline func for casCtx
|
||||
#include "inBufIL.h" // inline func for inBuf
|
||||
#include "casPVIIL.h" // inline func for casPVI
|
||||
#include "db_access.h"
|
||||
|
||||
VERSIONID(camsgtaskc,"%W% %G%")
|
||||
|
||||
@@ -124,59 +129,60 @@ void casClient::loadProtoJumpTable()
|
||||
|
||||
//
|
||||
// Request Protocol Jump Table
|
||||
// (use of & here is more portable)
|
||||
//
|
||||
casClient::msgHandlers[CA_PROTO_NOOP] =
|
||||
casClient::noopAction;
|
||||
&casClient::noopAction;
|
||||
casClient::msgHandlers[CA_PROTO_EVENT_ADD] =
|
||||
casClient::eventAddAction;
|
||||
&casClient::eventAddAction;
|
||||
casClient::msgHandlers[CA_PROTO_EVENT_CANCEL] =
|
||||
casClient::eventCancelAction;
|
||||
&casClient::eventCancelAction;
|
||||
casClient::msgHandlers[CA_PROTO_READ] =
|
||||
casClient::readAction;
|
||||
&casClient::readAction;
|
||||
casClient::msgHandlers[CA_PROTO_WRITE] =
|
||||
casClient::writeAction;
|
||||
&casClient::writeAction;
|
||||
casClient::msgHandlers[CA_PROTO_SNAPSHOT] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
casClient::msgHandlers[CA_PROTO_SEARCH] =
|
||||
casClient::searchAction;
|
||||
&casClient::searchAction;
|
||||
casClient::msgHandlers[CA_PROTO_BUILD] =
|
||||
casClient::ignoreMsgAction;
|
||||
&casClient::ignoreMsgAction;
|
||||
casClient::msgHandlers[CA_PROTO_EVENTS_OFF] =
|
||||
casClient::eventsOffAction;
|
||||
&casClient::eventsOffAction;
|
||||
casClient::msgHandlers[CA_PROTO_EVENTS_ON] =
|
||||
casClient::eventsOnAction;
|
||||
&casClient::eventsOnAction;
|
||||
casClient::msgHandlers[CA_PROTO_READ_SYNC] =
|
||||
casClient::readSyncAction;
|
||||
&casClient::readSyncAction;
|
||||
casClient::msgHandlers[CA_PROTO_ERROR] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
casClient::msgHandlers[CA_PROTO_CLEAR_CHANNEL] =
|
||||
casClient::clearChannelAction;
|
||||
&casClient::clearChannelAction;
|
||||
casClient::msgHandlers[CA_PROTO_RSRV_IS_UP] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
casClient::msgHandlers[CA_PROTO_NOT_FOUND] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
casClient::msgHandlers[CA_PROTO_READ_NOTIFY] =
|
||||
casClient::readNotifyAction;
|
||||
&casClient::readNotifyAction;
|
||||
casClient::msgHandlers[CA_PROTO_READ_BUILD] =
|
||||
casClient::ignoreMsgAction;
|
||||
&casClient::ignoreMsgAction;
|
||||
casClient::msgHandlers[REPEATER_CONFIRM] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
casClient::msgHandlers[CA_PROTO_CLAIM_CIU] =
|
||||
casClient::claimChannelAction;
|
||||
&casClient::claimChannelAction;
|
||||
casClient::msgHandlers[CA_PROTO_WRITE_NOTIFY] =
|
||||
casClient::writeNotifyAction;
|
||||
&casClient::writeNotifyAction;
|
||||
casClient::msgHandlers[CA_PROTO_CLIENT_NAME] =
|
||||
casClient::clientNameAction;
|
||||
&casClient::clientNameAction;
|
||||
casClient::msgHandlers[CA_PROTO_HOST_NAME] =
|
||||
casClient::hostNameAction;
|
||||
&casClient::hostNameAction;
|
||||
casClient::msgHandlers[CA_PROTO_ACCESS_RIGHTS] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
casClient::msgHandlers[CA_PROTO_ECHO] =
|
||||
casClient::echoAction;
|
||||
&casClient::echoAction;
|
||||
casClient::msgHandlers[REPEATER_REGISTER] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
casClient::msgHandlers[CA_PROTO_CLAIM_CIU_FAILED] =
|
||||
casClient::uknownMessageAction;
|
||||
&casClient::uknownMessageAction;
|
||||
|
||||
casClient::msgHandlersInit = TRUE;
|
||||
}
|
||||
@@ -552,7 +558,7 @@ void casClient::dumpMsg(const caHdr *mp, const void *dp)
|
||||
pciu = this->resIdToChannel(mp->m_cid);
|
||||
|
||||
if (pciu) {
|
||||
strncpy(pPVName, pciu->getPVI().resourceName(), sizeof(pPVName));
|
||||
strncpy(pPVName, pciu->getPVI()->getName(), sizeof(pPVName));
|
||||
if (&pciu->getClient()!=this) {
|
||||
strncat(pPVName, "!Bad Client!", sizeof(pPVName));
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.3 1996/12/11 00:59:37 jhill
|
||||
* added bad chan attachment detection
|
||||
*
|
||||
* Revision 1.2 1996/11/02 00:54:06 jhill
|
||||
* many improvements
|
||||
*
|
||||
@@ -42,8 +45,8 @@
|
||||
#ifndef casClientIL_h
|
||||
#define casClientIL_h
|
||||
|
||||
#include <caServerIIL.h> // caServerI inline func
|
||||
#include <casCtxIL.h> // caServerI inline func
|
||||
#include "caServerIIL.h" // caServerI inline func
|
||||
#include "casCtxIL.h" // caServerI inline func
|
||||
|
||||
//
|
||||
// find the channel associated with a resource id
|
||||
@@ -56,6 +59,15 @@ inline casChannelI *casClient::resIdToChannel(const caResId &id)
|
||||
// look up the id in a hash table
|
||||
//
|
||||
pChan = this->ctx.getServer()->resIdToChannel(id);
|
||||
|
||||
//
|
||||
// update the context
|
||||
//
|
||||
this->ctx.setChannel(pChan);
|
||||
if (!pChan) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// If the channel isnt attached to this client then
|
||||
// something has gone wrong
|
||||
@@ -63,13 +75,11 @@ inline casChannelI *casClient::resIdToChannel(const caResId &id)
|
||||
if (&pChan->getClient()!=this) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// update the context
|
||||
//
|
||||
this->ctx.setChannel(pChan);
|
||||
if (pChan) {
|
||||
this->ctx.setPV(&pChan->getPVI());
|
||||
}
|
||||
this->ctx.setPV(&pChan->getPVI());
|
||||
return pChan;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,13 +29,16 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.1.1.1 1996/06/20 00:28:15 jhill
|
||||
* ca server installation
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include "server.h"
|
||||
|
||||
#include <casChannelIIL.h>
|
||||
#include "casChannelIIL.h"
|
||||
|
||||
|
||||
//
|
||||
@@ -81,3 +84,22 @@ caStatus casClientMon::callBack(gdd &value)
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// casClientMon::destroy()
|
||||
//
|
||||
// this class is always created inside the server
|
||||
// lib with new
|
||||
//
|
||||
void casClientMon::destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
//
|
||||
// casClientMon::resourceType()
|
||||
//
|
||||
casResType casClientMon::resourceType() const
|
||||
{
|
||||
return casClientMonT;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.4 1996/11/02 00:54:07 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.3 1996/09/16 18:23:59 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -42,13 +45,13 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <server.h>
|
||||
#include <caServerIIL.h> // caServerI in line func
|
||||
#include <casAsyncIOIIL.h> // casAsyncIOI in line func
|
||||
#include <casEventSysIL.h> // casEventSys in line func
|
||||
#include <casCtxIL.h> // casCtx in line func
|
||||
#include <inBufIL.h> // inBuf in line func
|
||||
#include <outBufIL.h> // outBuf in line func
|
||||
#include "server.h"
|
||||
#include "caServerIIL.h" // caServerI in line func
|
||||
#include "casAsyncIOIIL.h" // casAsyncIOI in line func
|
||||
#include "casEventSysIL.h" // casEventSys in line func
|
||||
#include "casCtxIL.h" // casCtx in line func
|
||||
#include "inBufIL.h" // inBuf in line func
|
||||
#include "outBufIL.h" // outBuf in line func
|
||||
|
||||
//
|
||||
// casCoreClient::init()
|
||||
@@ -124,27 +127,26 @@ void casCoreClient::loadProtoJumpTable()
|
||||
//
|
||||
casCoreClient::~casCoreClient()
|
||||
{
|
||||
casAsyncIOI *pCurIO;
|
||||
|
||||
if (this->ctx.getServer()->getDebugLevel()>0u) {
|
||||
ca_printf ("CAS: Connection Terminated\n");
|
||||
}
|
||||
|
||||
this->osiLock();
|
||||
tsDLFwdIter<casAsyncIOI> iterIO(this->ioInProgList);
|
||||
tsDLIterBD<casAsyncIOI> iterIO(this->ioInProgList.first());
|
||||
tsDLIterBD<casAsyncIOI> tmpIO;
|
||||
tsDLIterBD<casAsyncIOI> eolIO;
|
||||
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
pCurIO = iterIO.next();
|
||||
while (pCurIO) {
|
||||
casAsyncIOI *pNextIO;
|
||||
while (iterIO!=eolIO) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
pNextIO = iterIO.next();
|
||||
pCurIO->destroy();
|
||||
pCurIO = pNextIO;
|
||||
tmpIO = iterIO;
|
||||
++tmpIO;
|
||||
iterIO->destroy();
|
||||
iterIO = tmpIO;
|
||||
}
|
||||
|
||||
this->osiUnlock();
|
||||
@@ -180,11 +182,11 @@ void casCoreClient::show (unsigned level) const
|
||||
// asynchronous completion
|
||||
//
|
||||
caStatus casCoreClient::asyncSearchResponse(casDGIntfIO &,
|
||||
const caAddr &, const caHdr &, const pvExistReturn &)
|
||||
const caAddr &, const caHdr &, const pvExistReturn)
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
caStatus casCoreClient::createChanResponse(const caHdr &, const pvExistReturn &)
|
||||
caStatus casCoreClient::createChanResponse(const caHdr &, const pvCreateReturn &)
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
@@ -213,6 +215,10 @@ caStatus casCoreClient::monitorResponse(casChannelI *, const caHdr &,
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
caStatus casCoreClient::accessRightsResponse(casChannelI *)
|
||||
{
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
|
||||
//
|
||||
// casCoreClient::installChannel()
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.1 1996/11/02 01:01:06 jhill
|
||||
* installed
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -74,6 +77,7 @@ inline void casCoreClient::removeAsyncIO(casAsyncIOI &ioIn)
|
||||
{
|
||||
this->osiLock();
|
||||
this->ioInProgList.remove(ioIn);
|
||||
this->ctx.getServer()->ioBlockedList::signal();
|
||||
this->osiUnlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
|
||||
#include <server.h>
|
||||
#include "server.h"
|
||||
|
||||
//
|
||||
// casCtx::show()
|
||||
//
|
||||
void casCtx::show (unsigned level) const
|
||||
{
|
||||
printf ("casCtx at %x\n", (unsigned) this);
|
||||
if (level >= 1u) {
|
||||
printf ("\tpMsg = %x\n", (unsigned) &this->msg);
|
||||
printf ("\tpData = %x\n", (unsigned) pData);
|
||||
printf ("\tpCAS = %x\n", (unsigned) pCAS);
|
||||
printf ("\tpClient = %x\n", (unsigned) pClient);
|
||||
printf ("\tpChannel = %x\n", (unsigned) pChannel);
|
||||
printf ("\tpPV = %x\n", (unsigned) pPV);
|
||||
printf ("casCtx at %lx\n", (unsigned long) this);
|
||||
if (level >= 3u) {
|
||||
printf ("\tpMsg = %lx\n", (unsigned long) &this->msg);
|
||||
printf ("\tpData = %lx\n", (unsigned long) pData);
|
||||
printf ("\tpCAS = %lx\n", (unsigned long) pCAS);
|
||||
printf ("\tpClient = %lx\n", (unsigned long) pClient);
|
||||
printf ("\tpChannel = %lx\n", (unsigned long) pChannel);
|
||||
printf ("\tpPV = %lx\n", (unsigned long) pPV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
inline casCtx::casCtx() :
|
||||
pData(NULL), pCAS(NULL), pClient(NULL),
|
||||
pChannel(NULL), pPV(NULL)
|
||||
pChannel(NULL), pPV(NULL), nAsyncIO(0u)
|
||||
{
|
||||
memset(&this->msg, 0, sizeof(this->msg));
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.8 1997/01/10 21:17:53 jhill
|
||||
* code around gnu g++ inline bug when -O isnt used
|
||||
*
|
||||
* Revision 1.7 1996/11/02 00:54:08 jhill
|
||||
* many improvements
|
||||
*
|
||||
@@ -53,14 +56,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <server.h>
|
||||
#include <caServerIIL.h> // caServerI inline func
|
||||
#include <casClientIL.h> // casClient inline func
|
||||
#include <dgOutBufIL.h> // dgOutBuf inline func
|
||||
#include <dgInBufIL.h> // dgInBuf inline func
|
||||
#include <casCtxIL.h> // casCtx inline func
|
||||
#include <casCoreClientIL.h> // casCoreClient inline func
|
||||
#include <gddApps.h>
|
||||
#include "server.h"
|
||||
#include "caServerIIL.h" // caServerI inline func
|
||||
#include "casClientIL.h" // casClient inline func
|
||||
#include "dgOutBufIL.h" // dgOutBuf inline func
|
||||
#include "dgInBufIL.h" // dgInBuf inline func
|
||||
#include "casCtxIL.h" // casCtx inline func
|
||||
#include "casCoreClientIL.h" // casCoreClient inline func
|
||||
#include "gddApps.h"
|
||||
|
||||
//
|
||||
// CA Server Datagram (DG) Client
|
||||
@@ -124,32 +127,68 @@ caStatus casDGClient::searchAction()
|
||||
void *dp = this->ctx.getData();
|
||||
const char *pChanName = (const char *) dp;
|
||||
caStatus status;
|
||||
pvExistReturn pver;
|
||||
|
||||
if (this->ctx.getServer()->getDebugLevel()>2u) {
|
||||
printf("client is searching for \"%s\"\n", pChanName);
|
||||
}
|
||||
|
||||
//
|
||||
// verify that we have sufficent memory for a PV and a
|
||||
// monitor prior to calling PV exist test so that when
|
||||
// the server runs out of memory we dont reply to
|
||||
// search requests, and therefore dont thrash through
|
||||
// caServer::pvExistTest() and casCreatePV::createPV()
|
||||
//
|
||||
#ifdef vxWorks
|
||||
# error code needs to be implemented here when we port
|
||||
# error to memory limited environment
|
||||
#endif
|
||||
|
||||
//
|
||||
// ask the server tool if this PV exists
|
||||
//
|
||||
pvExistReturn retVal =
|
||||
this->asyncIOFlag = 0u;
|
||||
casPVExistReturn retVal =
|
||||
this->ctx.getServer()->pvExistTest(this->ctx, pChanName);
|
||||
if (retVal.getStatus() == S_casApp_asyncCompletion) {
|
||||
status = S_cas_success;
|
||||
}
|
||||
else if (retVal.getStatus()==S_cas_ioBlocked) {
|
||||
//
|
||||
// If too many exist test IO operations are in progress
|
||||
// then we will just ignore this request (and wait for
|
||||
// the client to try again later)
|
||||
//
|
||||
status = S_cas_success;
|
||||
}
|
||||
else {
|
||||
status = this->searchResponse(*mp, retVal);
|
||||
if (retVal.getStatus()!=S_cas_success) {
|
||||
return retVal.getStatus();
|
||||
}
|
||||
|
||||
return S_cas_success;
|
||||
//
|
||||
// prevent problems when they initiate
|
||||
// async IO but dont return status
|
||||
// indicating so (and vise versa)
|
||||
//
|
||||
pver = retVal.getAppStat();
|
||||
if (this->asyncIOFlag) {
|
||||
pver = pverAsyncCompletion;
|
||||
}
|
||||
else if (pver == pverAsyncCompletion) {
|
||||
pver = pverDoesNotExistHere;
|
||||
errMessage(S_cas_badParameter,
|
||||
"- expected asynch IO creation from caServer::pvExistTest()");
|
||||
}
|
||||
|
||||
//
|
||||
// otherwise we assume sync IO operation was initiated
|
||||
//
|
||||
switch (pver) {
|
||||
case pverDoesNotExistHere:
|
||||
case pverAsyncCompletion:
|
||||
status = S_cas_success;
|
||||
break;
|
||||
|
||||
case pverExistsHere:
|
||||
status = this->searchResponse(*mp, retVal.getAppStat());
|
||||
break;
|
||||
|
||||
default:
|
||||
status = S_cas_badParameter;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,18 +196,22 @@ caStatus casDGClient::searchAction()
|
||||
// caStatus casDGClient::searchResponse()
|
||||
//
|
||||
caStatus casDGClient::searchResponse(const caHdr &msg,
|
||||
const pvExistReturn &retVal)
|
||||
const pvExistReturn retVal)
|
||||
{
|
||||
caStatus status;
|
||||
caHdr *search_reply;
|
||||
unsigned short *pMinorVersion;
|
||||
|
||||
this->ctx.getServer()->pvExistTestCompletion();
|
||||
|
||||
//
|
||||
// normal search failure is ignored
|
||||
//
|
||||
if (retVal.getStatus()==S_casApp_pvNotFound) {
|
||||
if (retVal==pverDoesNotExistHere) {
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
if (retVal!=pverExistsHere) {
|
||||
fprintf(stderr,
|
||||
"async exist completion with invalid return code \"pverAsynchCompletion\"?\n");
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
@@ -199,29 +242,6 @@ caStatus casDGClient::searchResponse(const caHdr &msg,
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// check for bad parameters
|
||||
//
|
||||
if (retVal.getStatus()) {
|
||||
errMessage(retVal.getStatus(),NULL);
|
||||
return S_cas_success;
|
||||
}
|
||||
if (retVal.getString()) {
|
||||
if (retVal.getString()[0]=='\0') {
|
||||
errMessage(S_cas_badParameter,
|
||||
"PV name descr is empty");
|
||||
return S_cas_success;
|
||||
}
|
||||
if (this->ctx.getServer()->getDebugLevel()>2u) {
|
||||
printf("Search request matched for PV=\"%s\"\n",
|
||||
retVal.getString());
|
||||
}
|
||||
}
|
||||
else {
|
||||
errMessage(S_cas_badParameter, "PV name descr is nill");
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
/*
|
||||
* obtain space for the reply message
|
||||
*/
|
||||
@@ -381,7 +401,7 @@ void casDGClient::processDG(casDGIntfIO &inMsgIO, casDGIntfIO &outMsgIO)
|
||||
// casDGClient::asyncSearchResp()
|
||||
//
|
||||
caStatus casDGClient::asyncSearchResponse(casDGIntfIO &outMsgIO, const caAddr &outAddr,
|
||||
const caHdr &msg, const pvExistReturn &retVal)
|
||||
const caHdr &msg, const pvExistReturn retVal)
|
||||
{
|
||||
caStatus stat;
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.5 1996/12/11 01:01:56 jhill
|
||||
* casEventMaskEntry constr does res tbl add
|
||||
*
|
||||
* Revision 1.4 1996/12/06 22:32:11 jhill
|
||||
* force virtual destructor
|
||||
*
|
||||
@@ -45,11 +48,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include "epicsAssert.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <server.h>
|
||||
#include "server.h"
|
||||
|
||||
#ifdef TEST
|
||||
main ()
|
||||
@@ -132,8 +135,12 @@ inline casEventMask casEventRegistry::maskAllocator()
|
||||
//
|
||||
casEventMask casEventRegistry::registerEvent(const char *pName)
|
||||
{
|
||||
//
|
||||
// NOTE: pName outlives id here
|
||||
// (so the refString option is ok)
|
||||
//
|
||||
stringId id (pName, stringId::refString);
|
||||
casEventMaskEntry *pEntry;
|
||||
stringId id (pName);
|
||||
casEventMask mask;
|
||||
|
||||
if (!this->hasBeenInitialized) {
|
||||
@@ -171,7 +178,7 @@ casEventMask casEventRegistry::registerEvent(const char *pName)
|
||||
//
|
||||
// casEventMask::show()
|
||||
//
|
||||
void casEventMask::show(unsigned level)
|
||||
void casEventMask::show(unsigned level) const
|
||||
{
|
||||
if (level>0u) {
|
||||
printf ("casEventMask = %x\n", this->mask);
|
||||
@@ -186,7 +193,7 @@ casEventMask::casEventMask (casEventRegistry ®, const char *pName)
|
||||
//
|
||||
// casEventRegistry::show()
|
||||
//
|
||||
void casEventRegistry::show(unsigned level)
|
||||
void casEventRegistry::show(unsigned level) const
|
||||
{
|
||||
if (!this->hasBeenInitialized) {
|
||||
printf ("casEventRegistry: not initialized\n");
|
||||
@@ -209,6 +216,7 @@ casEventMaskEntry::casEventMaskEntry(
|
||||
{
|
||||
int stat;
|
||||
|
||||
assert(this->resourceName()!=NULL);
|
||||
stat = this->reg.add(*this);
|
||||
assert(stat==0);
|
||||
}
|
||||
@@ -226,10 +234,18 @@ casEventMaskEntry::~casEventMaskEntry()
|
||||
this->reg.remove (*this);
|
||||
}
|
||||
|
||||
//
|
||||
// casEventMaskEntry::destroy()
|
||||
//
|
||||
void casEventMaskEntry::destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventMaskEntry::show()
|
||||
//
|
||||
void casEventMaskEntry::show (unsigned level)
|
||||
void casEventMaskEntry::show (unsigned level) const
|
||||
{
|
||||
this->casEventMask::show(level);
|
||||
this->stringId::show(level);
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.4 1996/12/11 01:02:35 jhill
|
||||
* removed casEventMaskEntry def
|
||||
*
|
||||
* Revision 1.3 1996/12/06 22:32:10 jhill
|
||||
* force virtual destructor
|
||||
*
|
||||
@@ -72,7 +75,7 @@ public:
|
||||
this->clear();
|
||||
}
|
||||
|
||||
void show (unsigned level);
|
||||
void show (unsigned level) const;
|
||||
|
||||
int eventsSelected()
|
||||
{
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.4 1996/11/02 00:54:12 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.3 1996/09/16 18:24:01 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -49,8 +52,8 @@
|
||||
/*
|
||||
* EPICS
|
||||
*/
|
||||
#include <server.h>
|
||||
#include <casEventSysIL.h> // casMonitor inline func
|
||||
#include "server.h"
|
||||
#include "casEventSysIL.h" // casMonitor inline func
|
||||
|
||||
//
|
||||
// casEventSys::show()
|
||||
@@ -167,6 +170,19 @@ casProcCond casEventSys::process()
|
||||
|
||||
this->mutex.osiUnlock();
|
||||
|
||||
//
|
||||
// allows the derived class to be informed that it
|
||||
// needs to delete itself via the event system
|
||||
//
|
||||
// this gets the server out of nasty situations
|
||||
// where the client needs to be deleted but
|
||||
// the caller may be using the client's "this"
|
||||
// pointer.
|
||||
//
|
||||
if (this->destroyPending) {
|
||||
cond = casProcDisconnect;
|
||||
}
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.3 1996/11/02 00:54:13 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.2 1996/09/16 18:24:02 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -54,7 +57,8 @@ inline casEventSys::casEventSys (casCoreClient &coreClientIn) :
|
||||
coreClient(coreClientIn),
|
||||
numEventBlocks(0u),
|
||||
maxLogEntries(individualEventEntries),
|
||||
eventsOff(aitFalse)
|
||||
eventsOff(aitFalse),
|
||||
destroyPending(aitFalse)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -115,6 +119,18 @@ void casEventSys::setEventsOff()
|
||||
this->eventsOff = aitTrue;
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::setDestroyPending()
|
||||
//
|
||||
void casEventSys::setDestroyPending()
|
||||
{
|
||||
this->destroyPending = aitTrue;
|
||||
//
|
||||
// wakes up the event queue consumer
|
||||
//
|
||||
this->coreClient.eventSignal();
|
||||
}
|
||||
|
||||
//
|
||||
// casEventSys::insertEventQueue()
|
||||
//
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.10 1997/01/10 21:17:55 jhill
|
||||
* code around gnu g++ inline bug when -O isnt used
|
||||
*
|
||||
* Revision 1.9 1996/12/06 22:33:49 jhill
|
||||
* virtual ~casPVI(), ~casPVListChan(), ~casChannelI()
|
||||
*
|
||||
@@ -96,7 +99,8 @@ class casRes : public uintRes<casRes>
|
||||
public:
|
||||
virtual ~casRes();
|
||||
virtual casResType resourceType() const = 0;
|
||||
virtual void show (unsigned level) = 0;
|
||||
virtual void show (unsigned level) const = 0;
|
||||
virtual void destroy() = 0;
|
||||
private:
|
||||
};
|
||||
|
||||
@@ -136,7 +140,7 @@ class casMonitor;
|
||||
class casMonEvent : public casEvent {
|
||||
public:
|
||||
//
|
||||
// only used when this part of another structure
|
||||
// only used when this is part of another structure
|
||||
// (and we need to postpone true construction)
|
||||
//
|
||||
inline casMonEvent ();
|
||||
@@ -145,8 +149,9 @@ public:
|
||||
|
||||
//
|
||||
// ~casMonEvent ()
|
||||
// (not inline because this is virtual in the base class)
|
||||
//
|
||||
inline ~casMonEvent ();
|
||||
~casMonEvent ();
|
||||
|
||||
caStatus cbFunc(casEventSys &);
|
||||
|
||||
@@ -180,7 +185,7 @@ public:
|
||||
|
||||
void post(const casEventMask &select, gdd &value);
|
||||
|
||||
virtual void show (unsigned level);
|
||||
virtual void show (unsigned level) const;
|
||||
virtual caStatus callBack(gdd &value)=0;
|
||||
|
||||
caResId getClientId() const
|
||||
@@ -260,6 +265,7 @@ class casAsyncIO;
|
||||
class casAsyncReadIO;
|
||||
class casAsyncWriteIO;
|
||||
class casAsyncPVExistIO;
|
||||
class casAsyncPVCreateIO;
|
||||
|
||||
class casAsyncIOI : public casEvent, public tsDLNode<casAsyncIOI> {
|
||||
public:
|
||||
@@ -279,7 +285,7 @@ public:
|
||||
|
||||
void destroyIfReadOP();
|
||||
|
||||
caServer *getCAS();
|
||||
caServer *getCAS() const;
|
||||
|
||||
inline void destroy();
|
||||
|
||||
@@ -294,6 +300,7 @@ private:
|
||||
unsigned posted:1;
|
||||
unsigned ioComplete:1;
|
||||
unsigned serverDelete:1;
|
||||
unsigned duplicate:1;
|
||||
//
|
||||
// casEvent virtual call back function
|
||||
// (called when IO completion event reaches top of event queue)
|
||||
@@ -411,7 +418,7 @@ public:
|
||||
//
|
||||
// place notification of IO completion on the event queue
|
||||
//
|
||||
caStatus postIOCompletion(const pvExistReturn &retVal);
|
||||
caStatus postIOCompletion(const pvExistReturn retVal);
|
||||
|
||||
caStatus cbFuncAsyncIO();
|
||||
casAsyncIO &getAsyncIO();
|
||||
@@ -422,16 +429,43 @@ private:
|
||||
const casOpaqueAddr dgOutAddr;
|
||||
};
|
||||
|
||||
//
|
||||
// casAsyncPVCIOI
|
||||
//
|
||||
// (server internal asynchronous read IO class)
|
||||
//
|
||||
class casAsyncPVCIOI : public casAsyncIOI {
|
||||
public:
|
||||
casAsyncPVCIOI(const casCtx &ctx, casAsyncPVCreateIO &ioIn);
|
||||
virtual ~casAsyncPVCIOI();
|
||||
|
||||
//
|
||||
// place notification of IO completion on the event queue
|
||||
//
|
||||
caStatus postIOCompletion(const pvCreateReturn &retVal);
|
||||
|
||||
caStatus cbFuncAsyncIO();
|
||||
casAsyncIO &getAsyncIO();
|
||||
private:
|
||||
caHdr const msg;
|
||||
pvCreateReturn retVal;
|
||||
};
|
||||
|
||||
class casChannel;
|
||||
class casPVI;
|
||||
|
||||
class casChannelI : public tsDLNode<casChannelI>, public casRes {
|
||||
//
|
||||
// casChannelI
|
||||
//
|
||||
// this derives from casEvent so that access rights
|
||||
// events can be posted
|
||||
//
|
||||
class casChannelI : public tsDLNode<casChannelI>, public casRes,
|
||||
public casEvent {
|
||||
public:
|
||||
casChannelI (const casCtx &ctx, casChannel &chanAdapter);
|
||||
virtual ~casChannelI();
|
||||
|
||||
void show (unsigned level);
|
||||
|
||||
casCoreClient &getClient() const
|
||||
{
|
||||
return this->client;
|
||||
@@ -475,20 +509,27 @@ public:
|
||||
|
||||
inline void postEvent (const casEventMask &select, gdd &event);
|
||||
|
||||
casResType resourceType() const
|
||||
{
|
||||
return casChanT;
|
||||
}
|
||||
virtual casResType resourceType() const;
|
||||
|
||||
inline void lock();
|
||||
inline void unlock();
|
||||
virtual void show (unsigned level) const;
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
inline void lock() const;
|
||||
inline void unlock() const;
|
||||
|
||||
inline void clientDestroy();
|
||||
|
||||
inline casChannel * operator -> ();
|
||||
inline casChannel * operator -> () const;
|
||||
|
||||
void clearOutstandingReads();
|
||||
|
||||
//
|
||||
// access rights event call back
|
||||
//
|
||||
caStatus cbFunc(casEventSys &);
|
||||
|
||||
inline void postAccessRightsEvent();
|
||||
protected:
|
||||
tsDLList<casMonitor> monitorList;
|
||||
tsDLList<casAsyncIOI> ioInProgList;
|
||||
@@ -497,6 +538,7 @@ protected:
|
||||
casChannel &chan;
|
||||
caResId const cid; // client id
|
||||
unsigned clientDestroyPending:1;
|
||||
unsigned accessRightsEvPending:1;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -514,23 +556,22 @@ class casCtx;
|
||||
class casChannel;
|
||||
class casPV;
|
||||
|
||||
//
|
||||
// casPVI
|
||||
//
|
||||
class casPVI :
|
||||
public stringId, // server PV name table installation
|
||||
public tsSLNode<casPVI>, // server PV name table installation
|
||||
public tsSLNode<casPVI>, // server resource table installation
|
||||
public casRes, // server resource table installation
|
||||
public ioBlockedList // list of clients io blocked on this pv
|
||||
{
|
||||
public:
|
||||
//
|
||||
// The PV name here must be the canonical and unique name
|
||||
// for the PV in this system
|
||||
//
|
||||
casPVI (caServerI &cas, const char * const pNameIn, casPV &pvAdapter);
|
||||
casPVI (caServer &cas, casPV &pvAdapter);
|
||||
virtual ~casPVI();
|
||||
|
||||
//
|
||||
// for use by the server library
|
||||
//
|
||||
inline caServerI &getCAS();
|
||||
inline caServerI &getCAS() const;
|
||||
|
||||
//
|
||||
// CA only does 1D arrays for now (and the new server
|
||||
@@ -547,7 +588,6 @@ public:
|
||||
//
|
||||
// only for use by casAsyncIOI
|
||||
//
|
||||
inline void registerIO();
|
||||
inline void unregisterIO();
|
||||
|
||||
//
|
||||
@@ -565,22 +605,25 @@ public:
|
||||
//
|
||||
inline void deleteSignal();
|
||||
|
||||
void show(unsigned level);
|
||||
|
||||
inline void postEvent (const casEventMask &select, gdd &event);
|
||||
|
||||
inline casPV *interfaceObjectPointer() const;
|
||||
|
||||
caServer *getExtServer();
|
||||
caServer *getExtServer() const;
|
||||
|
||||
//
|
||||
// bestDBRType()
|
||||
//
|
||||
inline caStatus bestDBRType (unsigned &dbrType);
|
||||
|
||||
inline aitBool okToBeginNewIO() const;
|
||||
|
||||
inline casPV * operator -> () const;
|
||||
|
||||
virtual casResType resourceType() const;
|
||||
|
||||
virtual void show(unsigned level) const;
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
private:
|
||||
tsDLList<casPVListChan> chanList;
|
||||
caServerI &cas;
|
||||
@@ -589,50 +632,7 @@ private:
|
||||
unsigned nIOAttached;
|
||||
unsigned destroyInProgress:1;
|
||||
|
||||
inline void lock();
|
||||
inline void unlock();
|
||||
inline void lock() const;
|
||||
inline void unlock() const;
|
||||
};
|
||||
|
||||
//
|
||||
// inline functions associated with the return arg from
|
||||
// caServer::pvExistTest()
|
||||
//
|
||||
inline pvExistReturn::pvExistReturn(caStatus status,
|
||||
char* pCanonicalNameStr) :
|
||||
stat(status), str(pCanonicalNameStr)
|
||||
{
|
||||
}
|
||||
inline pvExistReturn::pvExistReturn(caStatus status,
|
||||
const char* pCanonicalNameStr) :
|
||||
stat(status), str(pCanonicalNameStr)
|
||||
{
|
||||
}
|
||||
inline pvExistReturn::pvExistReturn(pvExistReturn &init) :
|
||||
stat(init.stat), str(init.str)
|
||||
{
|
||||
}
|
||||
inline pvExistReturn::pvExistReturn(const pvExistReturn &init) :
|
||||
stat(init.stat), str(init.str)
|
||||
{
|
||||
}
|
||||
inline const caStatus pvExistReturn::getStatus() const
|
||||
{
|
||||
return this->stat;
|
||||
}
|
||||
inline const char* pvExistReturn::getString() const
|
||||
{
|
||||
return str.string();
|
||||
}
|
||||
inline pvExistReturn& pvExistReturn::operator=(pvExistReturn &rhs)
|
||||
{
|
||||
this->stat = rhs.stat;
|
||||
this->str = rhs.str;
|
||||
return *this;
|
||||
}
|
||||
inline pvExistReturn& pvExistReturn::operator=(const pvExistReturn &rhs)
|
||||
{
|
||||
this->stat = rhs.stat;
|
||||
this->str = rhs.str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user