Compare commits

...

137 Commits

Author SHA1 Message Date
Janet B. Anderson
115f2b8a1e Bug fix 1997-05-08 18:28:06 +00:00
Janet B. Anderson
fefb8454c7 R3_13_0_beta9 1997-05-06 19:10:05 +00:00
Janet B. Anderson
e4cf1df857 Removed unused lines. 1997-05-06 15:55:23 +00:00
Janet B. Anderson
f3bd38caca Added comments 1997-05-06 15:54:34 +00:00
Janet B. Anderson
c104460654 Added cygwin32 changes. 1997-05-05 18:31:00 +00:00
Janet B. Anderson
fc3db2c3bf Allow site host architecture specific overrides 1997-05-05 17:56:58 +00:00
Janet B. Anderson
41e02220d1 Knts no longer needed. 1997-05-05 17:55:36 +00:00
Janet B. Anderson
8f5061b28e Initial version 1997-05-05 17:54:37 +00:00
Jeff Hill
5898d94c4c fixed use of event->pLastLog when event->npend should be used 1997-05-05 17:39:44 +00:00
Janet B. Anderson
b2ced4889b Modifications made for beta9. 1997-05-05 17:37:44 +00:00
Janet B. Anderson
a65e5f1f73 Removed redundant prototype 1997-05-05 17:31:05 +00:00
Marty Kraimer
839b8bdb5f Increase buffer size to 5000 bytes 1997-05-05 13:09:01 +00:00
Jeff Hill
421d98a936 moved pLog = NULL down 1997-05-05 04:50:11 +00:00
Jeff Hill
95b6d4a998 moved flow control to db event module 1997-05-05 04:49:16 +00:00
Jeff Hill
cc2ea961d7 added use of db events flow control 1997-05-05 04:48:30 +00:00
Jeff Hill
3a0de109a3 removed eventsoff flag 1997-05-05 04:47:54 +00:00
Jeff Hill
41aad467a6 added flow control mode 1997-05-05 04:46:14 +00:00
Jeff Hill
ebf6c4932a send_needed => pushPending, and added ca_number_iiu_in_fc 1997-05-05 04:45:25 +00:00
Jeff Hill
b587d3639f socket buf matches CA buf size, and pushPending flag added 1997-05-05 04:44:39 +00:00
Jeff Hill
7408f7f29f added ca_number_iiu_in_fc maintenance code 1997-05-05 04:43:37 +00:00
Jeff Hill
e2baae4281 fixed flow control off 1997-05-05 04:42:49 +00:00
Jeff Hill
b61b816c49 send_needed replaced by pushPending flag 1997-05-05 04:40:29 +00:00
Marty Kraimer
5257374a73 Allow null string 1997-05-02 20:19:56 +00:00
Marty Kraimer
f732ff2505 suppress error messages if dbCreateRecord called for existing record 1997-05-02 20:18:15 +00:00
Janet B. Anderson
8e2e15194a Added note about perl version. 1997-05-02 19:04:05 +00:00
Janet B. Anderson
4a3993c4e5 R3.13 updates 1997-05-02 16:25:42 +00:00
Janet B. Anderson
f11dadd032 Added missing definitions. 1997-05-02 16:24:31 +00:00
Janet B. Anderson
881cbd60e3 Added support for LIBNAME_CXX and BIN_INSTALLS 1997-05-02 16:22:20 +00:00
Jeff Hill
598e87d598 include getopt.h only on win32 1997-05-02 01:21:20 +00:00
Jeff Hill
6e8fc4f9c1 dll keyword adj 1997-05-01 23:57:50 +00:00
Jeff Hill
1be3c39e50 added getopt prototype (for NT) 1997-05-01 23:56:32 +00:00
Jeff Hill
fc48d2dd1d removed redundant prototype 1997-05-01 23:54:20 +00:00
Jeff Hill
11084a5dfc removed redundant prototypes 1997-05-01 23:52:14 +00:00
Jeff Hill
7946e9b921 DLL keyword adjustments 1997-05-01 23:51:07 +00:00
Jeff Hill
2a1f06cd2a replaced by installEpics.pl 1997-05-01 22:05:11 +00:00
Marty Kraimer
ccf3271fe1 Bug in dbDevice 1997-05-01 21:23:30 +00:00
Jeff Hill
c99ee0317c fixed conflict 1997-05-01 20:43:12 +00:00
Jeff Hill
5bf13da02c fixed conflict >>>>> 1997-05-01 20:30:15 +00:00
Jeff Hill
cbd5d9a36e removed conflict >>>>> 1997-05-01 20:26:07 +00:00
Jeff Hill
bb8e8f46cb new header file for ipAddrToA() 1997-05-01 19:59:09 +00:00
Jeff Hill
6b6e5e7515 updated dll keywords 1997-05-01 19:57:53 +00:00
Jeff Hill
0b0b23c6d6 removed ipAddrToA () prototype 1997-05-01 19:53:28 +00:00
Jeff Hill
1ed2559cc3 fixed unintialized variable bug 1997-05-01 19:46:32 +00:00
Jeff Hill
9a068b824d updated DLL keywords 1997-05-01 19:46:05 +00:00
Marty Kraimer
32a847087d Get rid of a lot of compiler warning messages 1997-04-30 19:22:22 +00:00
Marty Kraimer
67fbf5b746 For now keep both makeBaseApp and makeBaseApp.pl; Make compatible 1997-04-30 19:21:30 +00:00
Marty Kraimer
a0e8290c50 Fix compiler warning messages 1997-04-30 19:20:13 +00:00
Marty Kraimer
7cde4f8f2b Fixed most compiler warning messages 1997-04-30 19:20:01 +00:00
Marty Kraimer
437142b5bb Fix compiler warning messages 1997-04-30 19:12:25 +00:00
Marty Kraimer
42adbd20c8 move errhash defs. Add modules to Makefiles 1997-04-30 19:11:22 +00:00
Marty Kraimer
85a2ef6e4d Fix long memory free list problem 1997-04-30 19:10:04 +00:00
Marty Kraimer
62ce79e147 Extra useful routines. First is dbTranslateEscape 1997-04-30 19:07:57 +00:00
Marty Kraimer
3a840f6e2f Still original version 1997-04-30 19:04:09 +00:00
Marty Kraimer
69c62573b0 added function prototypes that have no nice place to go 1997-04-30 19:02:55 +00:00
Marty Kraimer
e1e8a34b2f Fixed many compiler warning messages 1997-04-30 19:02:21 +00:00
Marty Kraimer
13c9ae5fe3 Get rid of 1997-04-30 19:01:32 +00:00
Marty Kraimer
6912ff4929 Take VX_WARN_YES from config 1997-04-30 19:00:45 +00:00
Marty Kraimer
0e387c8936 Fixed most compiler warning mesdsages 1997-04-30 18:59:04 +00:00
Marty Kraimer
e8e3b5226e Fixed most compiler warning messages 1997-04-30 18:58:52 +00:00
Marty Kraimer
b87f049c2d Replace dbVarSub with macLib.
Allow C style escape sequences
Fix long vx memory free list problem
Fix most compiler warning messages
1997-04-30 18:54:10 +00:00
Marty Kraimer
0d7698e0d4 Allow c type escape sequences; Fix problem of long vx free memory list 1997-04-30 18:48:42 +00:00
Marty Kraimer
ebbaee5ed2 Fix compiler flags 1997-04-30 18:39:18 +00:00
Marty Kraimer
bff266bef3 Fixed compiler warning messages 1997-04-30 18:37:50 +00:00
Marty Kraimer
1d6f9f80f6 added dbGetPdbAddrFromLink. Fixed cimpiler warning messages 1997-04-30 18:36:33 +00:00
Marty Kraimer
8a298ab07c Fix compiler warning messages 1997-04-30 18:29:35 +00:00
Marty Kraimer
7f317f4d55 replace bcopt by memcpy 1997-04-30 18:28:08 +00:00
Marty Kraimer
50b19bc74f fix compiler warning messages 1997-04-30 18:26:53 +00:00
Marty Kraimer
9f35f8043e VX_WARN_YES = -Wall -pedantic -ansi 1997-04-30 18:23:47 +00:00
Jeff Hill
19091f245b fixed warnings 1997-04-29 06:50:35 +00:00
Jeff Hill
0bc395108d C++ compatibility 1997-04-29 06:34:39 +00:00
Jeff Hill
2b6367e1d4 use matching buffer sizes 1997-04-29 06:22:10 +00:00
Jeff Hill
6fb8477b3a C++ compatibility 1997-04-29 06:21:13 +00:00
Jeff Hill
39c22d2ee0 use free lists 1997-04-29 06:17:18 +00:00
Jeff Hill
721840498c use const in inet_addr () proto 1997-04-29 06:16:23 +00:00
Jeff Hill
56e35d8305 fixed exit when working problem 1997-04-29 06:15:34 +00:00
Jeff Hill
a42a244aed reserve less event buffers 1997-04-29 06:15:00 +00:00
Jeff Hill
b8dba0a4ad fixed warnings 1997-04-29 06:10:25 +00:00
Jeff Hill
fe9f9b91fb local host connect compatible 1997-04-29 06:07:16 +00:00
Jeff Hill
206a04e15f use free list 1997-04-29 06:05:57 +00:00
Jeff Hill
db11fd957d use matching buffer sizes 1997-04-23 17:27:01 +00:00
Jeff Hill
2517d52437 fixed WIN32 DLL symbol exports 1997-04-23 17:23:05 +00:00
Jeff Hill
f85aba61ed removed ipAddrToA.cc 1997-04-23 17:20:18 +00:00
Jeff Hill
147403b0e5 added new func and removed variables 1997-04-23 17:19:03 +00:00
Jeff Hill
afa84f396b added additional error codes 1997-04-23 17:17:29 +00:00
Jeff Hill
9888b965d8 rem _WINDLL => bad when other DLLs involved 1997-04-23 17:15:55 +00:00
Jeff Hill
c3e2f58d96 fixed export of symbols from WIN32 DLL 1997-04-23 17:13:07 +00:00
Jeff Hill
697200e942 fixed warnings 1997-04-23 17:12:19 +00:00
Jeff Hill
33b940562e min() => tsMin() also max 1997-04-23 17:11:50 +00:00
Jeff Hill
08f2298215 stringId::T[] => stringIdFastHash[] 1997-04-23 17:11:15 +00:00
Jeff Hill
8c992ed466 init ref differently for MS VC++ 1997-04-23 17:07:23 +00:00
Jeff Hill
c442950e5f min() => tsMin() 1997-04-23 17:06:44 +00:00
Jeff Hill
0a5dffc069 pc port changes 1997-04-23 17:05:10 +00:00
Jeff Hill
744a0de15d fixed win32 lib build 1997-04-23 17:00:19 +00:00
Jeff Hill
7c42f005db remove -D_REENTRANT flag 1997-04-23 16:55:23 +00:00
Jeff Hill
652cb0d66c added optimize/debug flags 1997-04-23 16:54:44 +00:00
Jeff Hill
9f77fbccd1 .EPICS_CONFIG => EPICS_CONFIG for win32 1997-04-23 16:50:55 +00:00
Jeff Hill
de2864a5a5 removed files 1997-04-21 15:02:52 +00:00
Jeff Hill
2caf1628ca added b-tree templ 1997-04-11 20:53:38 +00:00
Jeff Hill
f1865a507c added no arg reset() to bwd iter 1997-04-11 20:49:48 +00:00
Jeff Hill
8013fecb61 kay's perl branch 1997-04-11 20:44:03 +00:00
Jeff Hill
8d6deea83d merged Kay's perl proto branch 1997-04-11 20:28:21 +00:00
Jeff Hill
da3eed2a6f added const to failureNotify() 1997-04-11 20:24:13 +00:00
Jeff Hill
5de817b531 changes from Pam Gurd 1997-04-10 21:54:37 +00:00
Jeff Hill
a173792b1f C++ conditional build 1997-04-10 21:52:49 +00:00
Jeff Hill
6af690f524 use SYS_PROD_LIBS_ 1997-04-10 21:51:31 +00:00
Jeff Hill
1891940018 compile C++ only if CPLUSPLUS isnt empty 1997-04-10 21:32:42 +00:00
Jeff Hill
6adb68d7d6 fixed depen 1997-04-10 20:07:15 +00:00
Jeff Hill
c1225d880e use SYS_PROD_LIBS 1997-04-10 20:05:19 +00:00
Jeff Hill
017686e0f6 use free list lib 1997-04-10 20:04:51 +00:00
Jeff Hill
f61f401683 use include not include <> 1997-04-10 20:03:53 +00:00
Jeff Hill
3a5e5fc5d7 VMS changes 1997-04-10 20:02:55 +00:00
Jeff Hill
8d0712bea4 winsock II changes 1997-04-10 20:02:05 +00:00
Jeff Hill
0804f7fb08 api changes 1997-04-10 20:01:14 +00:00
Jeff Hill
7a8878dec6 API changes 1997-04-10 19:56:38 +00:00
Jeff Hill
92ae7b14c4 use SYS_PROD_LIBS_DEFAULT 1997-04-10 19:54:14 +00:00
Jeff Hill
eda3aae608 API changes 1997-04-10 19:51:14 +00:00
Jeff Hill
8e363122b3 added new functions 1997-04-10 19:47:35 +00:00
Jeff Hill
ff378e17c9 new env param decl 1997-04-10 19:46:59 +00:00
Jeff Hill
5e1157d363 added sigPipeIgnore 1997-04-10 19:46:31 +00:00
Jeff Hill
d3c6310bb1 API changes and include with not <> 1997-04-10 19:45:43 +00:00
Jeff Hill
5c4d82cacc API changes 1997-04-10 19:43:15 +00:00
Jeff Hill
414c8ed603 installed 1997-04-10 19:38:14 +00:00
Jeff Hill
603c598e14 added new files 1997-04-10 19:36:53 +00:00
Jeff Hill
a3cad9563f asynch connect, faster connect, ... 1997-04-10 19:26:27 +00:00
Jeff Hill
cb95ba41ac deleted 1997-04-09 22:23:57 +00:00
Marty Kraimer
8e000eb634 Forgot to compile before committing 1997-04-09 19:50:39 +00:00
Marty Kraimer
b00f152456 makesure GPIBFASTO has val in range 1997-04-09 19:35:56 +00:00
Marty Kraimer
566d70bf9c Restore original 1997-04-09 18:33:49 +00:00
Marty Kraimer
bc6bf59bda In devGpibLib_mbboGpibWork make sure val is in range 1997-04-09 18:14:43 +00:00
Jim Kowalkowski
6fcbfa15b3 Changed these to use the dbmf library for malloc/free of buffers 1997-04-07 20:17:43 +00:00
Jim Kowalkowski
121a2dc9ae Added a simple library for doing malloc/free from a buffer pool 1997-04-07 20:16:42 +00:00
Janet B. Anderson
35f9a872f7 Added CXXLDLIBS and USR_CXXLDFLAGS. 1997-03-26 18:44:44 +00:00
Janet B. Anderson
0efb9a0c8c Added LDLIBS 1997-03-26 18:39:18 +00:00
Janet B. Anderson
63da245439 Use LINK.c from config 1997-03-26 18:38:26 +00:00
Jim Kowalkowski
8b83afc1bb fixed bug in gddDestructor constructor. 1997-03-24 12:41:49 +00:00
Jim Kowalkowski
54e6f9aed1 *** empty log message *** 1997-03-21 01:56:12 +00:00
Jim Kowalkowski
4c99a53852 fixed a problem with gddDestructor and reference counting 1997-03-17 17:14:48 +00:00
594 changed files with 17079 additions and 13093 deletions

View File

@@ -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

View File

@@ -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
View 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!

View File

@@ -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

View File

@@ -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.

View File

@@ -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)

View File

@@ -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
#

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -1,4 +1,3 @@
SHELL=knts
# BUILD_TYPE
# Currently either Vx or Unix

View File

@@ -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

View File

@@ -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)

View File

@@ -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}"

View File

@@ -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

View File

@@ -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.
#

View File

@@ -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 ?

View 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
View 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 = .

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)/%: ../%

View File

@@ -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 $@"

View File

@@ -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)

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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>

View File

@@ -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"

View File

@@ -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);
}
%%

View File

@@ -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

View File

@@ -1,9 +1,6 @@
TOP = ../../..
include $(TOP)/config/CONFIG_BASE
USR_CFLAGS = -ansi
VX_WARN_YES = -Wall -pedantic
MENUS += menuConvert.h
BPTS += bptTypeJdegC.dbd

View File

@@ -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>

View File

@@ -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
$
$! ************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
{

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -19,7 +19,7 @@
*
*/
#include <iocinf.h>
#include "iocinf.h"
int main()
{

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 ()

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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!!

View File

@@ -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

View File

@@ -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"
/*

View File

@@ -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

View File

@@ -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;

View File

@@ -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));
}
}
}

View File

@@ -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;
}
}

View File

@@ -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
*

View File

@@ -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
}
}

View File

@@ -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;
}

View File

@@ -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).

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -3,5 +3,5 @@
// Example EPICS CA server
//
#include <exServer.h>
#include "exServer.h"

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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";
}

View File

@@ -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 &copyIn) :
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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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
//

View File

@@ -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.

View File

@@ -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();

View File

@@ -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));
}
//

View File

@@ -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;

View File

@@ -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

View File

@@ -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();
}
//

View 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;
}

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()
{
}

View File

@@ -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()

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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()

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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));
}

View File

@@ -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;

View File

@@ -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 &reg, 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);

View File

@@ -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()
{

View File

@@ -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;
}

View File

@@ -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()
//

View File

@@ -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