Compare commits

..

147 Commits

Author SHA1 Message Date
Ralph Lange
b319b4722f Update version to 3.15.6-rc1 2018-10-05 15:21:58 +02:00
Ralph Lange
b4cc5fdf4b doc: update release checklist 2018-10-05 15:21:57 +02:00
Ralph Lange
d35835659c libCom/osi: Add epicsStdio functions to std namespace; allow to skip macro magic
(fixes lp:1786927)
2018-10-05 10:54:10 +02:00
Andrew Johnson
cbb13bf6b1 Darwin: Don't link using -flat_namespace 2018-09-18 10:22:29 -05:00
Andrew Johnson
150d764d28 Merge 3.14.12.8 (+ the Travis fix) into 3.15 2018-09-17 16:15:55 -05:00
Andrew Johnson
7dd1ea4cab GNU Make 3.81 (as used on Travis) doesn't have 'undefine' 2018-09-17 10:24:51 -05:00
Andrew Johnson
922ed30136 Set EPICS_DEV_SNAPSHOT for the final 3.14.12.8 release 2018-09-14 13:44:05 -05:00
Andrew Johnson
9f9f119e7e Release notes about iocLogServer 2018-09-14 13:21:06 -05:00
Andrew Johnson
d8214a4531 Merge Martin Konrad's fix-logserver-file-limit branch into 3.14 2018-09-14 12:24:14 -05:00
Andrew Johnson
120b100e7e startup: Fix EHA argument quoting per J. Lewis Muir 2018-09-14 12:15:29 -05:00
Andrew Johnson
949e9d788a Make startup/EpicsHostArch script executable 2018-09-14 11:23:14 -05:00
Martin Konrad
27c6e6a385 Make EpicsHostArch compatible with sh 2018-09-14 09:12:10 -04:00
Andrew Johnson
4b59476170 Merge branch 'tidy-startup' into 3.14 2018-09-13 16:49:21 -05:00
Andrew Johnson
526b565c6b configure/CONFIG: Undefine EHA after use 2018-09-10 18:19:03 -05:00
Andrew Johnson
1b7b2bcceb Update README's list of files 2018-09-10 18:16:16 -05:00
Andrew Johnson
49c925d064 Fix shebang line in makeInstallDir.pl 2018-09-10 16:08:19 -05:00
Ralph Lange
6a2ed4b333 libcom/osi/windows: log errors using fprintf() instead of pop-up
(fixes lp:1785712)
2018-09-05 21:47:25 +02:00
Andrew Johnson
d3bcf5737f Latest Xcode also doesn't like compiling system() for iOS 2018-08-17 14:57:22 -05:00
Andrew Johnson
6c5505ad3e osiClockTime again: Don't compile ClockTimeSync() on iOS either 2018-08-17 13:48:00 -05:00
Andrew Johnson
4247d98b08 Add fix to Release Notes 2018-08-17 13:25:18 -05:00
Andrew Johnson
13735a8088 Fix for lp: #1786320
A dbCa link that reads an enum as a string subscribes to the link target
twice, once as DBR_TIME_ENUM and again as DBR_TIME_STRING. This change
prevents ENUM updates from triggering CP/CPP record processing if there
is also a STRING subscription for this link.
2018-08-17 13:18:47 -05:00
Andrew Johnson
58d4242b68 osiClockTime: Only call clock_setting() on embedded OSs
An update to Apple's XCode broke the iOS build because they have
added Posix CLOCK_REALTIME support since this code was written and
now if you compile a call to clock_settime() it stops the build.
2018-08-17 13:09:33 -05:00
Martin Konrad
8e42f516b0 iocLogserver: allow log file limit to be disabled
According to the Application Developer's Guide setting the environment
variable EPICS_IOC_LOG_FILE_LIMIT=0 should disable the limit on the
file size.
2018-08-13 18:16:26 -04:00
Andrew Johnson
9051cdbb34 Added a simpler startup/EpicsHostArch for backwards-compatibility
Many downstream modules seem to be using the EpicsHostArch script in
their CI build scripts and would break if we remove that. I created
a new version that finds and execs the Perl script directly.

Also reworded and expanded the Release Notes about the EpicsHostArch
scripts.
2018-08-10 15:20:29 -05:00
Andrew Johnson
8ffea9de27 Remove macLib warning indicators
Only add ',undefined' tags to macLib output when we aren't
suppressing warnings, e.g. using msi's -V flag.
2018-08-10 14:12:19 -05:00
Andrew Johnson
2548a37267 Update/clean up EpicsHostArch.pl 2018-08-08 16:53:32 -05:00
Andrew Johnson
1dc1b25aaa caget.pl: Add missing acks and ackt metadata to display output 2018-07-31 17:58:38 -05:00
Andrew Johnson
fb31dd784b recGbl: Prevent record alarm severities > INVALID_ALARM 2018-07-31 16:30:11 -05:00
Andrew Johnson
fe7260e263 msi: Source code reformatting, typo fixes, unify messages
Added lots of debug tracing macros.
Release notes.
2018-07-25 00:47:18 -05:00
Andrew Johnson
67e2b74758 Fix for lp: #1503661
Delete output file if parse errors found in substitution file
2018-07-25 00:31:48 -05:00
Andrew Johnson
c09b6e2f1b libCom: Add and use a -o<filename> option to e_flex
Note that like the -S option the filename must follow immediately in
the same command-line argument with no space.
2018-07-21 01:47:33 -05:00
Andrew Johnson
45be2306bd Add missing includes for db_post_events() 2018-07-21 01:04:05 -05:00
Andrew Johnson
6027f906c3 Merge documentation changes from 3.14 into 3.15 2018-07-20 23:29:47 -05:00
Andrew Johnson
ec351c5e2f Fix for lp: #1730727
Post monitors on all array-length record fields (often NORD)
when their values get changed.
2018-07-20 23:10:34 -05:00
89870e2817 Remove trailing space in license of startup/unix.* 2018-07-20 17:47:39 -05:00
4e9cf72d71 Remove execute file mode bit on EpicsHostArch.pl 2018-07-20 17:45:47 -05:00
80869a0868 Rewrite startup/windows.bat
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:43:01 -05:00
998fa984ba Rewrite startup/win32.bat
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:39:29 -05:00
31844af88e Rewrite startup/unix.csh
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:29:47 -05:00
8f161f9463 Rewrite startup/unix.sh
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:18:22 -05:00
e0399478ad Remove startup/cygwin.bat
Cygwin is no longer supported for Microsoft API builds, so remove it.
2018-07-20 17:14:43 -05:00
Andrew Johnson
2a2a1e54ac Post-tag version number update 2018-07-19 12:35:40 -05:00
Andrew Johnson
20d2cff501 Update version number to 3.14.12.8-rc1 2018-07-19 12:31:52 -05:00
Andrew Johnson
860ce156a2 Documentation updates for 3.14.12.8 2018-07-19 12:20:41 -05:00
Andrew Johnson
0f21196670 Merge 3.14 branch into 3.15 2018-07-13 13:23:11 -05:00
Andrew Johnson
31fc35fbe8 dbCa: Fix for lp: #541221
I'd looked at this a few times since it was reported, but never
actually fixed the bug I described in the comments. Apparently
the only thing left to do was to store the eventId and use it to
clear the subscription when we saw a type-change to a PV.
2018-07-13 13:05:54 -05:00
Andrew Johnson
f892731b3f Fix epicsCalcTest for gcc 7.1.0 on minGW
Another case where the compile-time evaluation returns +1
but at run-time isnan() returns -1.
2018-06-29 15:03:45 -05:00
ab493264b2 Make EpicsHostArch.pl print newline
Print a newline after the EPICS host architecture spec.  This is typical
for a UNIX-like program (e.g., date).
2018-06-26 17:56:58 -05:00
68779943eb Remove execute file mode bit 2018-06-26 16:34:04 -05:00
7a5ff26984 Remove EpicsHostArch 2018-06-26 16:20:07 -05:00
eae59183cc Rename Site.{cshrc,profile} to unix.{csh,sh} 2018-06-26 16:09:04 -05:00
Andrew Johnson
8144d2ea01 Add HOWTO: Converting Wiki Record Reference to POD 2018-06-26 14:47:59 -05:00
Andrew Johnson
b32629c3bf Start release notes for tidy-startup branch. 2018-06-26 11:23:35 -05:00
Andrew Johnson
220e404203 Move EpicsHostArch.pl into src/tools, install to lib/perl 2018-06-26 11:23:15 -05:00
Andrew Johnson
8f55a1307d startup: Update win*.bat files 2018-06-22 14:54:06 -05:00
Ralph Lange
e459e8bdd4 cas: don't spin on zero-length search requests
(fix lp:1743321)
2018-06-07 11:32:16 +02:00
Ralph Lange
b558bd9b16 Cherry-picking e794639e from 3.15
(lp:1730982 lp:1762543)
2018-06-07 11:21:04 +02:00
Michael Davidsaver
3c16c3c0da Cherry-picking d2b0e920 from 3.15
(closes lp:1773373)
2018-06-07 11:07:29 +02:00
Andrew Johnson
a9d7f7be13 Template iocBoot/ioc Makefile fix for Unix-like OSs
Fixes lp: #1766349
2018-06-04 23:14:45 -05:00
Andrew Johnson
23c4eb42a3 Perl s/use vars/our/ 2018-05-28 17:31:16 -05:00
Andrew Johnson
6d7f70f200 Merge changes from 3.14 branch into 3.15 2018-05-28 17:00:35 -05:00
Andrew Johnson
67844bacc3 Perl s/use vars/our/ 2018-05-28 16:13:14 -05:00
Ralph Lange
7e7d230d8c templates: fix warnings for xxxRecord.c in exampleApp
(fixes #1772833)
2018-05-23 09:24:56 +02:00
Andrew Johnson
c1ece40f41 Updated Release Notes for Base-3.14.12.8 2018-05-19 22:42:23 -05:00
Andrew Johnson
a732539eee epicsMath.h defines 'finite()' not 'isfinite()' 2018-05-19 21:14:36 -05:00
Ralph Lange
3bc0805a89 rec: fix missing includes in longin/longout 2018-05-18 09:54:42 +02:00
Ralph Lange
c72e35c769 Merge Ralph's fix-1770292 branch into 3.14 2018-05-17 17:16:07 +02:00
Ralph Lange
2d9c5e99a1 db: correctly convert NaN alarm levels to integers
(fixes lp #1771298)
2018-05-15 11:18:11 +02:00
Ralph Lange
ca22d50831 rec: consistent get_alarm_double() for longin/longout
(fixes lp #1770292)
2018-05-15 11:18:10 +02:00
Michael Davidsaver
4972803ce2 scanEventTest: use testSyncCallback() 2018-05-14 10:49:49 -07:00
Michael Davidsaver
3b7e348a8c dbUnitTest.h add callback sync. and global mutex
Add testSyncCallback() to wait for in queued and
in-progress callbacks to complete.

Also add testGlobalLock() to help tests avoid
use after free when destroying sync. primitives.
2018-05-14 10:49:49 -07:00
Michael Davidsaver
00a974ce52 callback.h: add epicsCallback alternative to CALLBACK
Add epicsCallback as an IDE friendly alternative to CALLBACK.

IDEs like qtcreator have long been confused by the use
of CALLBACK, a name which has long been used by other libraries,
which prevents code using it from being parsed correctly.
2018-05-14 10:49:49 -07:00
Michael Davidsaver
490c504736 scanEventTest: use dbUnitTest.h for IOC lifecycle 2018-05-14 10:49:49 -07:00
Andrew Johnson
49371cfe00 Fix RTEMS build in src/std/rec/test
Also back-ported Michael's change from commit b9b8cde5f6 to avoid
using callocMustSucceed() in eventNameToHandle()
2018-05-12 22:25:15 -05:00
Andrew Johnson
06ad4a0d70 Merge Bruce Hill's pv-name-in-ca-error-msgs branch into 3.15
Actually this is fixing CAS error messages.
I added the additional changes suggested by Ralph in his code-review.
2018-05-12 21:37:44 -05:00
Andrew Johnson
a2ae07dfcd Merge Dirk Zimoch's named-events-backward-compatibility branch into 3.15 2018-05-12 21:15:26 -05:00
Andrew Johnson
b539ced6d5 Merge J. Lewis Muir's doc-filters-typo branch into 3.15 2018-05-12 20:54:20 -05:00
Andrew Johnson
1b332361e7 Merge changes from 3.14 into 3.15 2018-05-12 20:47:54 -05:00
Andrew Johnson
5cb91d9f6d Merge Ben Franksen's deadlock_warning branch into 3.14 2018-05-12 20:20:30 -05:00
Andrew Johnson
116c90c2ea Reformatting, no code changes 2018-05-03 14:40:12 -05:00
Andrew Johnson
3f3696fb91 dbStatic: Prevent modifying a NAME field using a DB file
Fixes LP: #1597809
2018-05-03 14:28:44 -05:00
Benjamin Franksen
91ce807e8b Fix for lp: #1751380
Add warnings about possible deadlock to the docs for ca_clear_channel,
ca_clear_subscription, and ca_context_destroy.
2018-04-11 12:58:28 +02:00
Andrew Johnson
3d88316eab Merge 3.14 into 3.15 (MSVC absolute filenames fix) 2018-03-26 16:49:28 -05:00
Andrew Johnson
b9443f8813 Tell MSVC to use absolute filenames in diagnostics (-FC flag) 2018-03-23 11:39:53 -05:00
Andrew Johnson
d8802c8b24 Merge 3.14 into 3.15 2018-03-15 17:46:48 -05:00
Andrew Johnson
b7d4609e57 Merge Bruce Hill's camonitor-server-relative-ts-bug-3.14 branch 2018-03-15 17:33:32 -05:00
Andrew Johnson
7b5b23f6d3 Merge 3.14 into 3.15 2018-03-15 17:11:20 -05:00
Andrew Johnson
c8a7e1597d VxWorks Timezone updates
Remove 2017; fix hour in MET settings
2018-03-15 10:57:55 -05:00
Andrew Johnson
8333338f99 Merge 3.14 into 3.15 2018-03-14 16:08:07 -05:00
Andrew Johnson
ceaff61c09 Pull in the podToHtml.pl script and rules from 3.15
This lets src/cap5 build with Perl installations that lack Perl's
podchecker and pod2html scripts (e.g. Fedora 27).
2018-03-14 14:12:12 -05:00
Andrew Johnson
2307e94d1c Rules for building bootable TESTPROD_RTEMS targets
Previously if you wanted a .boot file it had to be installed.
2018-03-12 16:34:54 -05:00
Bruce Hill
05a3699b49 Update pcas CA error msgs to include the pv name for easier debugging. 2018-03-09 21:23:43 -08:00
Andrew Johnson
be8f35d782 Fix for lp: #1754298
Cleaned up and reformatted since Dirk's original.
2018-03-09 12:46:46 -06:00
Bruce Hill
6cc623a7b4 Fixed camonitor server side relative timestamps bug
tsFirst needs to get initialized from the first server side
timestamp instead of the client side tsNow.
2018-03-08 01:40:11 -08:00
2b4a9632b7 update RELEASE_NOTES for named event fix 2018-03-07 14:51:38 +01:00
396cf4ee3f remove special handling for inf and nan events 2018-03-07 14:49:12 +01:00
Andrew Johnson
a9764c8f62 tools/caput: Report errors from ca_array_put*()
Fixes LP: #1747983
2018-03-04 15:51:39 -06:00
Andrew Johnson
98d9ea4545 ca/client: Catch by reference, missing '&' 2018-03-04 15:45:15 -06:00
Andrew Johnson
8eb4eec7d2 Corrected fix from Bruce Hill's Github PR#19 2018-03-03 17:17:34 -06:00
Andrew Johnson
98930eebc4 strcpy() -> strncpy() changes from Bruce Hill
Also added some additional static assertions for string field sizes.
2018-03-03 00:12:59 -06:00
e50c468512 moved scanEventTest from src/ioc/db/test to src/std/rec/test 2018-02-26 11:41:54 +01:00
Andrew Johnson
c18b6f2ccf Deny use of dbgf, dbpf, dbtr, dbtgf and dbtpf before iocInit
Can't use locking dbAccess routines until lock-sets have been calculated.
Fixes LP: #1725248
2018-02-24 20:15:08 -06:00
Andrew Johnson
e41f8bf518 Translate and escape chars in info tag strings
Fixes LP: #1716998
2018-02-24 19:11:54 -06:00
Andrew Johnson
ae548d3400 Remove cantProceed() from dbGetLink() and dbPutLink()
Fixes LP: #1528314
Affects 3.15 branch only.
2018-02-24 17:40:45 -06:00
428a8f57e9 Fix typos in Channel Filters doc 2018-02-20 10:20:37 -06:00
29795656e6 bugfix for soft events >= 256 2018-02-20 09:53:06 +01:00
b2d6b67b06 removed obsolete code in scanpel 2018-02-16 11:03:12 +01:00
1e9826d187 add tests for calculated numeric soft events 2018-02-13 15:36:21 +01:00
0691fc5f57 fix scanEvent test 2018-02-13 14:10:29 +01:00
8a3080c16f added test for named soft events 2018-02-13 13:50:19 +01:00
d19afc73af Updated RELEASE_NOTES.html with soft event fix. 2018-02-12 12:06:12 +01:00
adf5375616 fix scanpel glob matching 2018-02-12 09:01:05 +01:00
Andrew Johnson
550beeab9f More clang warning clean-ups
The short => int change is a UB issue, the second argument to va_start()
must be of a type that does not undergo promotion. See
https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP58-CPP.+Pass+an+object+of+the+correct+type+to+va_start
2018-02-09 11:29:16 -06:00
Andrew Johnson
bf91275200 Merge clang fixes from 3.14 into 3.15 2018-02-09 11:16:26 -06:00
Andrew Johnson
ac4d5c95ac Clean up some compiler warnings from clang 2018-02-09 10:56:52 -06:00
7d836d9554 some cleanup and scanpel improvement 2018-02-09 16:58:36 +01:00
51e492fbb1 Fix numeric events: any number from 0 up to less than 256 is theated as an integer event. Event 0 is no event. 2018-02-09 14:37:45 +01:00
Andrew Johnson
61296b8cff Merge 3.14 into 3.15
Fix for LP: #1743076
2018-02-05 12:03:28 -06:00
Andrew Johnson
de442e9584 Fix for LP: #1743076
Never zero the CA client context private ID.
2018-02-05 12:02:13 -06:00
Andrew Johnson
ac367398b3 Merge fix for lp: #1747091 from 3.14 into 3.15 2018-02-02 17:49:00 -06:00
Andrew Johnson
713c2d5080 Fix for lp: #1747091
generalTimeGetEvent()
2018-02-02 17:47:35 -06:00
Andrew Johnson
af07016464 Merge 3.14 branch into 3.15
Actually a different fix to Michael's 3.14 commit due to divergent code.
2018-02-01 14:20:47 -06:00
Michael Davidsaver
734d16291f rsrv: buffer for IP too small
An IPv4 address and port number
has 21 characters max.
2018-02-01 09:42:51 -08:00
Andrew Johnson
f1e5e9689b Merge 3.14 branch into 3.15 2018-02-01 11:23:29 -06:00
Andrew Johnson
1454f42a27 Config fix for parallel builds with MSVC 2015 and later
From Mark Rivers and Freddie Akeroyd.
2018-02-01 11:19:08 -06:00
Andrew Johnson
ddbdcf9462 rec/test: Add missing filename to DBDDEPENDS_FILES 2018-01-21 00:44:10 -06:00
Andrew Johnson
729e6fda4d tools: Add some context to the 'Undefined macro' warning
Mark Rivers saw this warning when he forgot to configure and build a
dependent module properly. The additional information given by this
change would have helped him track down the problem faster.
2018-01-19 13:14:13 -06:00
Andrew Johnson
0315e90e6e Revert "tools: Use Carp"
This reverts commit f207b00b05.

None of these warn/die messages request a stack dump since they all
end with \n, but carp & croak ignore that.
2018-01-19 11:06:23 -06:00
Andrew Johnson
66c6aaa44f Merge URL updates from 3.14 branch into 3.15 2018-01-18 23:46:42 -06:00
Andrew Johnson
c830a3a4ee Updated links to new EPICS website at Argonne
Only done for documents that are still present in EPICS 7.
2018-01-18 23:35:09 -06:00
Andrew Johnson
8766ce05aa Fix slow callback test failures.
Slow callbacks no longer cause test failures, now they just emit a
diagnostic. Jenkins on MacOS frequently failed those tests.

We should never test for something that we can't fix.
2018-01-04 11:41:38 -06:00
Ralph Lange
8f62940265 Merge appveyor change from 3.14 2018-01-04 09:03:50 +01:00
Ralph Lange
8a1477ecab appveyor-ci: update APS download URL 2018-01-04 09:00:18 +01:00
Ralph Lange
89cbb95c2c Merge appveyor changes from 3.14 2017-12-19 09:52:15 +01:00
Ralph Lange
006ce1a240 appveyor-ci: remove VS 2008, add VS 2017 2017-12-19 09:39:57 +01:00
Ralph Lange
276dee2c3e appveyor-ci: use curl for download of make.zip 2017-12-19 09:39:10 +01:00
Andrew Johnson
98a2871727 Reset SNAPSHOT to -DEV after tagging 3.14.12.7 2017-12-15 16:09:21 -06:00
Andrew Johnson
5ca1bb3bd5 Set SNAPSHOT for 3.14.12.7 final release 2017-12-15 16:06:08 -06:00
Andrew Johnson
f6be3c7f70 Set snapshot to -rc1-DEV 2017-12-08 16:40:08 -06:00
Andrew Johnson
00924dcba0 About to tag 3.14.12.7-rc1 2017-12-08 16:37:03 -06:00
Andrew Johnson
3b0f34e0be Fix recursive check in Release.pm 2017-12-06 16:29:31 -06:00
Andrew Johnson
db005ac3fe RULES_TARGET: Define $(lib)_DIR before it is needed
TESTLIBRARY products were being installed, because an executable
that was linked to one added a dependency assuming it would be in
the INSTALL_LIB directory. The $(lib)_DIR was being set too late
for test libraries, so the fallback location was used instead.
This fix sets $(lib)_DIR for test libraries before any rules use it.
2017-11-17 14:55:50 -06:00
Andrew Johnson
0f0deb8903 Merge fixups/db_close_events into 3.15 2017-11-15 21:23:28 -06:00
Andrew Johnson
baf997193e Merge aSubRecord fixes from 3.14 into 3.15 2017-11-15 21:15:51 -06:00
Andrew Johnson
5278799575 aSubRecord: Copy the right amount of data
Initialize OVLx from VALx with NEVx elements, size from FTVx
2017-11-15 20:59:06 -06:00
Michael Davidsaver
e794639e31 ioc/db: avoid possible race in db_close_events()
lp:1730982
2017-11-08 14:42:08 -06:00
Michael Davidsaver
2af98c33c9 std/rec: aSub handle INAM changing outputs
Allow EFLG="On Change" to work with INAM.
2017-11-08 14:29:30 -06:00
1394 changed files with 253224 additions and 2434 deletions

View File

@@ -1,77 +0,0 @@
#!/bin/sh
#
# Make tar for git repo w/ one level of sub modules.
#
set -e
TOPREV="$1"
FINALTAR="$2"
PREFIX="$3"
if ! [ "$TOPREV" ]
then
cat <<EOF >&2
usage: $0 [rev] [outfile.tar.gz] [prefix/]
"<rev>" may be any git revision spec. (tag, branch, or commit id).
Output file may be .tar.gz, .tar.bz2, or any extension supported by "tar -a".
If output file name is omitted, then "<rev>.tar.gz" is the default.
If prefix is omitted, then the default is "<rev>/".
EOF
exit 1
fi
[ "$FINALTAR" ] || FINALTAR="$TOPREV.tar.gz"
[ "PREFIX" ] || PREFIX="$TOPREV/"
# temporary directory w/ automatic cleanup
TDIR=`mktemp -d`
trap 'rm -rf "$TDIR"' EXIT INT QUIT TERM
mkdir "$TDIR"/tar
echo "Export revision $TOPREV as $FINALTAR with prefix $PREFIX"
# Use git-archive to copy files at the given revision into our temp. dir.
# Respects 'export-exclude' in .gitattributes files.
git archive --prefix=$PREFIX $TOPREV | tar -C "$TDIR"/tar -x
# use ls-tree instead of submodule-foreach to capture submodule revision associated with supermodule rev.
#
# sub-modules appear in tree as eg.:
# 160000 commit c3a6cfcf0dad4a4eeecf59b474710d06ff3eb68a modules/ca
git ls-tree -r $TOPREV | awk '/^[0-9]+ commit / {print $3, $4}' | \
while read HASH MODDIR
do
echo "visit $HASH $MODDIR"
(cd $MODDIR && git archive --prefix=${PREFIX}${MODDIR}/ $HASH) | tar -C "$TDIR"/tar -x
done
# make a list of files copied and filter out undesirables
(cd "$TDIR"/tar && find .) > "$TDIR"/list.1
sed \
-e '/.*ci$/d' \
-e '/.*ci\//d' \
-e '/.*jenkins$/d' \
-e '/.*jenkins\//d' \
-e '/\.git/d' \
-e '/\.project/d' \
-e '/.*\.travis\.yml$/d' \
-e '/.*\.appveyor\.yml$/d' \
"$TDIR"/list.1 > "$TDIR"/list.2
if ! diff -u "$TDIR"/list.1 "$TDIR"/list.2
then
echo "Warning: prohibited files being ignored"
fi
# Use the filtered list to build the final tar
# The -a option chooses compression automatically based on output file name.
tar -C "$TDIR"/tar --files-from="$TDIR"/list.2 -caf "$FINALTAR"
echo "Wrote $FINALTAR"

4
.gitattributes vendored
View File

@@ -1,4 +0,0 @@
.ci/ export-ignore
.appveyor.yml export-ignore
.travis.yml export-ignore
README export-subst

1
.gitignore vendored
View File

@@ -7,7 +7,6 @@
/include/
/templates/
/configure/*.local
/modules/RELEASE.local
O.*/
/QtC-*
*.orig

36
.gitmodules vendored
View File

@@ -1,36 +0,0 @@
[submodule "modules/libcom"]
path = modules/libcom
url = ./
branch = libcom/master
[submodule "modules/database"]
path = modules/database
url = ./
branch = database/master
[submodule "modules/ca"]
path = modules/ca
url = ./
branch = ca/master
[submodule "modules/pvData"]
path = modules/pvData
url = https://github.com/epics-base/pvDataCPP
branch = master
[submodule "modules/pvAccess"]
path = modules/pvAccess
url = https://github.com/epics-base/pvAccessCPP
branch = master
[submodule "modules/normativeTypes"]
path = modules/normativeTypes
url = https://github.com/epics-base/normativeTypesCPP
branch = master
[submodule "modules/pvaClient"]
path = modules/pvaClient
url = https://github.com/epics-base/pvaClientCPP
branch = master
[submodule "modules/pvDatabase"]
path = modules/pvDatabase
url = https://github.com/epics-base/pvDatabaseCPP
branch = master
[submodule "modules/pva2pva"]
path = modules/pva2pva
url = https://github.com/epics-base/pva2pva
branch = master

View File

@@ -3,6 +3,16 @@ dist: trusty
language: c
compiler:
- gcc
env:
- CMPLR=gcc
- CMPLR=gcc EXTRA=CMD_CXXFLAGS=-std=c++11
- CMPLR=gcc STATIC=YES
- CMPLR=clang
- CMPLR=clang STATIC=YES
- WINE=32 TEST=NO STATIC=YES
- WINE=32 TEST=NO STATIC=NO
- RTEMS=4.10 TEST=NO
- RTEMS=4.9 TEST=NO
addons:
apt:
packages:
@@ -18,16 +28,5 @@ addons:
cache:
directories:
- $HOME/.cache
install:
- ./.ci/travis-prepare.sh
script:
- ./.ci/travis-build.sh
env:
- BRCORE=master BRLIBCOM=master BRCA=master
- CMPLR=clang
- USR_CXXFLAGS=-std=c++11
- CMPLR=clang USR_CXXFLAGS=-std=c++11
- WINE=32 TEST=NO STATIC=YES
- WINE=32 TEST=NO STATIC=NO
- RTEMS=4.10 TEST=NO
- RTEMS=4.9 TEST=NO
install: sh ci/travis-prepare.sh </dev/null
script: sh ci/travis-build.sh </dev/null

View File

@@ -4,7 +4,7 @@
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
# in file LICENSE that is included with this distribution.
#*************************************************************************
TOP = .
@@ -14,12 +14,8 @@ include $(TOP)/configure/CONFIG
TOOLS = $(TOP)/src/tools
DIRS += configure src
src_DEPEND_DIRS = configure
DIRS += test
test_DEPEND_DIRS = src
DIRS += modules
modules_DEPEND_DIRS = src
include $(TOP)/configure/RULES_TOP

15
README
View File

@@ -2,14 +2,14 @@
EPICS Base - the central core of a control system toolkit
---------------------------------------------------------
Copyright UChicago Argonne LLC, as Operator of Argonne
National Laboratory.
Copyright (c) 1991-2003 The University of Chicago, as Operator
of Argonne National Laboratory.
Copyright (c) 1991-2003 The Regents of the University of
California, as Operator of Los Alamos National Laboratory.
EPICS Base is distributed subject to a Software License
Agreement found in the file LICENSE that is included with
this distribution.
EPICS Base Versions 3.13.7 and higher are distributed
subject to a Software License Agreement found in the
file LICENSE that is included with this distribution.
---------------------------------------------------------
@@ -20,8 +20,5 @@ Additional information about EPICS including mailing list
archives and subscription instructions, documentation and
training materials, additional components, links to other
websites etc. is available on the EPICS home page at
http://www.aps.anl.gov/epics/
https://epics.anl.gov/
$Format:%cD$
$Format:%H$
https://code.launchpad.net/epics-base

View File

@@ -40,11 +40,12 @@ configuration:
# Environment variables: compiler toolchain
environment:
matrix:
- TOOLCHAIN: 9.0
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLCHAIN: 2017
- TOOLCHAIN: cygwin
- TOOLCHAIN: mingw
@@ -57,8 +58,6 @@ platform:
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- platform: x64
TOOLCHAIN: 9.0
- platform: x64
TOOLCHAIN: 10.0
@@ -67,13 +66,13 @@ matrix:
#---------------------------------#
install:
- cmd: .ci/appveyor-prepare.bat
- cmd: ci/appveyor-prepare.bat
build_script:
- cmd: .ci/appveyor-make.bat
- cmd: ci/appveyor-make.bat
test_script:
- cmd: .ci/appveyor-make.bat runtests
- cmd: ci/appveyor-make.bat runtests
#---------------------------------#
# notifications #

View File

@@ -1,6 +1,6 @@
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - toolchain version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
@@ -57,10 +57,22 @@ if "%TOOLCHAIN%"=="mingw" (
)
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
if not exist "%VSINSTALL%\" set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio\%TOOLCHAIN%\Community"
if not exist "%VSINSTALL%\" goto MSMissing
set "MAKE=C:\tools\make"
echo [INFO] APPVEYOR_BUILD_WORKER_IMAGE=%APPVEYOR_BUILD_WORKER_IMAGE%
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
where cl
@@ -79,12 +91,19 @@ if "%OS%"=="64BIT" (
)
) else (
set EPICS_HOST_ARCH=win32-x86%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" x86
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
)
if exist "%VSINSTALL%\VC\bin\vcvars32.bat" (
call "%VSINSTALL%\VC\bin\vcvars32.bat"
where cl

View File

@@ -65,6 +65,6 @@ if "%TOOLCHAIN%"=="mingw" (
)
echo [INFO] Installing Make 4.1
@powershell -Command "(new-object net.webclient).DownloadFile('https://www.aps.anl.gov/epics/download/tools/make-4.1-win64.zip', 'C:\tools\make-4.1.zip')"
curl -fsS --retry 3 -o C:\tools\make-4.1.zip https://epics.anl.gov/download/tools/make-4.1-win64.zip
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip

4
.ci/travis-build.sh → ci/travis-build.sh Executable file → Normal file
View File

@@ -17,7 +17,7 @@ ticker() {
CACHEKEY=1
EPICS_HOST_ARCH=`sh startup/EpicsHostArch`
EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
@@ -85,6 +85,6 @@ make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make -j2 tapfiles
make tapfiles
make -s test-results
fi

6
.ci/travis-prepare.sh → ci/travis-prepare.sh Executable file → Normal file
View File

@@ -38,9 +38,3 @@ then
fi
cd "$CURDIR"
cat <<EOF >> configure/CONFIG_SITE
USR_CPPFLAGS += $USR_CPPFLAGS
USR_CFLAGS += $USR_CFLAGS
USR_CXXFLAGS += $USR_CXXFLAGS
EOF

View File

@@ -20,11 +20,15 @@ else
endif
# Provide a default if the user hasn't set EPICS_HOST_ARCH
ifeq ($(origin EPICS_HOST_ARCH), undefined)
# NB: We use a simply expanded variable here for performance:
EPICS_HOST_ARCH := $(shell $(CONFIG)/../startup/EpicsHostArch.pl)
endif
#
ifeq ($(origin EPICS_HOST_ARCH), undefined)
# Bootstrapping ...
EHA := $(firstword $(wildcard $(EPICS_BASE)/lib/perl/EpicsHostArch.pl \
$(TOP)/src/tools/EpicsHostArch.pl))
# NB: We use a simply expanded variable here for performance:
export EPICS_HOST_ARCH := $(shell perl $(EHA))
EHA :=
endif
-include $(CONFIG)/RELEASE
-include $(CONFIG)/RELEASE.$(EPICS_HOST_ARCH)

View File

@@ -3,12 +3,13 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
# EPICS BASE Versions 3.13.7
# and higher are distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
#---------------------------------------------------------------
# EPICS Base directories
# Epics base directories
EPICS_BASE_HOST_BIN = $(EPICS_BASE)/bin/$(EPICS_HOST_ARCH)
EPICS_BASE_HOST_LIB = $(EPICS_BASE)/lib/$(EPICS_HOST_ARCH)
@@ -17,6 +18,17 @@ ifdef T_A
EPICS_BASE_BIN = $(EPICS_BASE)/bin/$(T_A)
endif
#---------------------------------------------------------------
# Epics base Ioc libraries
EPICS_BASE_IOC_LIBS += dbRecStd dbCore ca Com
#---------------------------------------------------------------
# Epics base Host libraries
EPICS_BASE_HOST_LIBS += cas gdd
EPICS_BASE_HOST_LIBS += ca Com
#---------------------------------------------------------------
# Version number for base shared libraries (and win32 products)
@@ -27,6 +39,17 @@ ifdef BASE_TOP
PROD_VERSION = $(EPICS_VERSION).$(EPICS_REVISION)
endif # BASE_TOP
#---------------------------------------------------------------
# Base c preprocessor flags
BASE_CPPFLAGS =
# osithread default stack
OSITHREAD_USE_DEFAULT_STACK = NO
OSITHREAD_DEFAULT_STACK_FLAGS_YES = -DOSITHREAD_USE_DEFAULT_STACK
OSITHREAD_DEFAULT_STACK_FLAGS_NO =
BASE_CPPFLAGS += $(OSITHREAD_DEFAULT_STACK_FLAGS_$(OSITHREAD_USE_DEFAULT_STACK))
#---------------------------------------------------------------
# Where to find the installed build tools
# Windows does not like commands with relative paths starting ../
@@ -36,21 +59,60 @@ TOOLS = $(abspath $(EPICS_BASE_HOST_BIN))
FIND_TOOL = $(firstword $(wildcard $(TOOLS)/$(1) $(TOP)/src/tools/$(1)))
#---------------------------------------------------------------
# EPICS Base build tools and tool flags
# Epics base build tools and tool flags
PODTOHTML = $(PERL) $(TOOLS)/podToHtml.pl
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG)
MAKEBPT = $(TOOLS)/makeBpt$(HOSTEXE)
DBEXPAND = $(PERL) $(TOOLS)/dbdExpand.pl
DBTORECORDTYPEH = $(PERL) $(TOOLS)/dbdToRecordtypeH.pl
DBTOMENUH = $(PERL) $(TOOLS)/dbdToMenuH.pl
REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
#---------------------------------------------------------------
#-------------------------------------------------------
# tools for installing libraries and products
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(QUIET_FLAG)
INSTALL_QUIETLY := $(if $(findstring s,$(MAKEFLAGS)),-q,)
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(INSTALL_QUIETLY)
INSTALL_PRODUCT = $(INSTALL)
INSTALL_LIBRARY = $(INSTALL)
#---------------------------------------------------------------
# tools for making header dependencies and variable replacement
MKMF = $(PERL) $(TOOLS)/mkmf.pl
REPLACEVAR = $(PERL) $(TOOLS)/replaceVAR.pl
# tools for making header dependancies and variable replacement
MKMF = $(PERL) $(TOOLS)/mkmf.pl
REPLACEVAR = $(PERL) $(TOOLS)/replaceVAR.pl
#---------------------------------------------------------------
# private versions of lex/yacc from EPICS
EYACC = $(TOOLS)/antelope$(HOSTEXE)
ELEX = $(TOOLS)/e_flex$(HOSTEXE) -S$(EPICS_BASE)/include/flex.skel.static
YACC = $(EYACC)
LEX = $(ELEX)
#---------------------------------------------------------------
# Our use of msi is incompatible with older versions
MSI3_15 = $(EPICS_BASE_HOST_BIN)/msi
#---------------------------------------------------------------
# External tools and tool flags - must be in path or defined in application
ADL2DL ?= adl2dl
# sch2edif compiler and flags
SCH2EDIF = sch2edif
SCH2EDIF_PATH =
SCH2EDIF_SYSFLAGS = -n -ap -p.+..+$(SCH2EDIF_PATH)+$(CAPFAST_TEMPLATES)/sym+
SCH2EDIF_FLAGS =
# e2db and flags
# - again there is an assumption where edb.def is installed.
E2DB ?= e2db
E2DB_SYSFLAGS = -ate -d $(CAPFAST_TEMPLATES)/edb.def
E2DB_FLAGS =
DBST ?= dbst

View File

@@ -4,7 +4,7 @@
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
# in the file LICENSE that is included with this distribution.
#*************************************************************************
#
# EPICS Version information
@@ -15,31 +15,19 @@
# EPICS_SITE_VERSION is defined in CONFIG_SITE for sites that want a local
# version number to be included in the reported version string.
# We define BASE_3_14 and BASE_3_15 as NO and BASE_3_16 as YES, so
# ifdef BASE_3_14
# true for 3.14 or later
# ifdef BASE_3_15
# true for 3.15 or later
# ifeq ($(BASE_3_14),YES)
# true for 3.14.x only
# ifeq ($(BASE_3_15),YES)
# true for 3.15 only
# ifeq ($(BASE_3_16),YES)
# true for 3.16 only.
# In 3.15 we still define BASE_3_14 so "ifdef BASE_3_14" means
# 3.14 or later, but "ifeq ($(BASE_3_14),YES)" means 3.14 only.
BASE_3_14 = NO
BASE_3_15 = NO
BASE_3_16 = NO
BASE_7_0 = YES
BASE_3_15 = YES
# EPICS_VERSION must be a number >0 and <256
EPICS_VERSION = 7
EPICS_VERSION = 3
# EPICS_REVISION must be a number >=0 and <256
EPICS_REVISION = 0
EPICS_REVISION = 15
# EPICS_MODIFICATION must be a number >=0 and <256
EPICS_MODIFICATION = 1
EPICS_MODIFICATION = 6
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero
@@ -47,11 +35,11 @@ EPICS_PATCH_LEVEL = 0
# This will end in -DEV between official releases
#EPICS_DEV_SNAPSHOT=-DEV
EPICS_DEV_SNAPSHOT=-pre1
#EPICS_DEV_SNAPSHOT=-pre1
#EPICS_DEV_SNAPSHOT=-pre1-DEV
#EPICS_DEV_SNAPSHOT=-pre2
#EPICS_DEV_SNAPSHOT=-pre2-DEV
#EPICS_DEV_SNAPSHOT=-rc1
EPICS_DEV_SNAPSHOT=-rc1
#EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV

View File

@@ -38,6 +38,10 @@ BUILD_ARCHS = $(EPICS_HOST_ARCH) $(CROSS1) $(CROSS2)
# otherwise override this in os/CONFIG_SITE.<host_arch>.Common
PERL = perl -CSD
#-------------------------------------------------------
# dbst based database optimization default
DB_OPT = NO
#-------------------------------------------------------
# Check configure/RELEASE file for consistency
CHECK_RELEASE_YES = checkRelease
@@ -79,7 +83,6 @@ IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION))
# Make echo output - suppress echoing if make's '-s' flag is set
NOP = :
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
QUIET_FLAG := $(if $(findstring s,$(MAKEFLAGS)),-q,)
#-------------------------------------------------------
ifdef T_A
@@ -329,14 +332,6 @@ COMPILE.cpp = $(CCC) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES)
# C preprocessor command
PREPROCESS.cpp = $(CPP) $(CPPFLAGS) $(INCLUDES) $< > $@
#--------------------------------------------------
# genVersion header defaults
# C macro name
GENVERSIONMACRO = VCSVERSION
# C macro default value (empty to use date+time)
GENVERSIONDEFAULT =
#--------------------------------------------------
# Header dependency file generation

View File

@@ -35,10 +35,8 @@ EPICS_CA_CONN_TMO=30.0
EPICS_CA_REPEATER_PORT=5065
EPICS_CA_SERVER_PORT=5064
EPICS_CA_MAX_ARRAY_BYTES=16384
EPICS_CA_AUTO_ARRAY_BYTES=YES
EPICS_CA_BEACON_PERIOD=15.0
EPICS_CA_MAX_SEARCH_PERIOD=300.0
EPICS_CA_MCAST_TTL=1
EPICS_CAS_BEACON_PERIOD=
EPICS_CAS_BEACON_PORT=
EPICS_CAS_AUTO_BEACON_ADDR_LIST=""
@@ -47,9 +45,6 @@ EPICS_CAS_SERVER_PORT=
EPICS_CAS_INTF_ADDR_LIST=""
EPICS_CAS_IGNORE_ADDR_LIST=""
# Servers to disable
EPICS_IOC_IGNORE_SERVERS=""
# Log Server:
# EPICS_IOC_LOG_PORT Log server port number etc.
EPICS_IOC_LOG_PORT=7004

View File

@@ -34,35 +34,30 @@
# The future dates below assume the rules don't get changed;
# see http://www.timeanddate.com/time/dst/2018.html to check.
#
# DST for 2017 US: Mar 12 - Nov 05
# EU: Mar 26 - Oct 29
EPICS_TIMEZONE = CUS::360:031202:110502
#EPICS_TIMEZONE = MET::-60:032602:102902
#
# DST for 2018 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
#EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102802
EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102803
#
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
#EPICS_TIMEZONE = CUS::360:031002:110302
#EPICS_TIMEZONE = MET::-60:033102:102702
#EPICS_TIMEZONE = MET::-60:033102:102703
#
# DST for 2020 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
#EPICS_TIMEZONE = CUS::360:030802:110102
#EPICS_TIMEZONE = MET::-60:032902:102502
#EPICS_TIMEZONE = MET::-60:032902:102503
#
# DST for 2021 US: Mar 14 - Nov 07
# EU: Mar 28 - Oct 31
#EPICS_TIMEZONE = CUS::360:031402:110702
#EPICS_TIMEZONE = MET::-60:032802:103102
#EPICS_TIMEZONE = MET::-60:032802:103103
#
# DST for 2022 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
#EPICS_TIMEZONE = CUS::360:031302:110602
#EPICS_TIMEZONE = MET::-60:032702:103002
#EPICS_TIMEZONE = MET::-60:032702:103003
# EPICS_TS_NTP_INET
# NTP time server ip address for VxWorks and RTEMS.
@@ -74,11 +69,8 @@ EPICS_TS_NTP_INET=
# Prompt string
# IOCSH_HISTSIZE
# Number of lines of command history to keep.
# IOCSH_HISTEDIT_DISABLE
# Prevents use of readline or equivalent if defined.
IOCSH_PS1="epics> "
IOCSH_HISTSIZE=50
IOCSH_HISTEDIT_DISABLE=
# Log Server:
# EPICS_IOC_LOG_INET

View File

@@ -8,12 +8,10 @@
#*************************************************************************
#RULES.Db
# Set db substitutions and template file suffixes
# Set db substitutions file suffix
SUBST_SUFFIX ?= .substitutions
TEMPL_SUFFIX ?= .template
#---------------------------------------------------------------
# vpath
##################################################### vpath
vpath %.pm $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
vpath %.pod $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
@@ -21,13 +19,12 @@ vpath %.dbd $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
vpath %.db $(USR_VPATH) $(SRC_DIRS) $(dir $(DB))
vpath %.vdb $(USR_VPATH) $(SRC_DIRS) $(dir $(DB))
vpath %$(SUBST_SUFFIX) $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %$(TEMPL_SUFFIX) $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %.template $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath bpt%.data $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %.acf $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %.acs $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
#---------------------------------------------------------------
# dbflags dbdflags
##################################################### dbflags dbdflags
DBD_SEARCH_DIRS = . .. $(COMMON_DIR) $(SRC_DIRS) $(INSTALL_DBD) $(RELEASE_DBD_DIRS)
DB_SEARCH_DIRS = . .. $(COMMON_DIR) $(SRC_DIRS) $(INSTALL_DB) $(RELEASE_DB_DIRS)
@@ -36,15 +33,13 @@ DBDFLAGS = $(USR_DBDFLAGS) $(CMD_DBDFLAGS) $(addprefix -I,$(DBD_SEARCH_DIRS))
DBFLAGS = $($*_DBFLAGS) $(USR_DBFLAGS) $(CMD_DBFLAGS) $(addprefix -I,$(DB_SEARCH_DIRS))
REGRDDFLAGS = $(DBDFLAGS) $($*_REGRDDFLAGS) $(USR_REGRDDFLAGS) $(CMD_REGRDDFLAGS)
#---------------------------------------------------------------
# Targets
##################################################### Targets
# ---------------------------------------------------
# To allow os specific dbd files AND have the -j option work properly,
CROSS_TARGET_OS_TYPES = $(sort $(foreach target, \
$(EPICS_HOST_ARCH) $(CROSS_COMPILER_TARGET_ARCHS), \
$(firstword $(subst -, ,$(target)))))
CROSS_TARGET_OS_TYPES = $(sort $(foreach target, \
$(EPICS_HOST_ARCH) $(CROSS_COMPILER_TARGET_ARCHS),$(firstword $(subst -, ,$(target)))))
DBD += $(foreach type, $(CROSS_TARGET_OS_TYPES), $(DBD_$(type)))
# Users add os specific dbd files to a Makefile as follows
@@ -91,28 +86,31 @@ SOURCE_DB_bbb = $(foreach dir, $(GENERIC_SRC_DIRS), $(SOURCE_DB_aaa) )
SOURCE_DB_aaa = $(addsuffix /$(file), $(dir) )
COMMONS = $(COMMON_DIR)/*.dbd $(COMMON_DIR)/*.db $(COMMON_DIR)/*.h \
$(COMMON_DIR)/*$(SUBST_SUFFIX) $(COMMON_DIR)/*$(TEMPL_SUFFIX)
$(COMMON_DIR)/*$(SUBST_SUFFIX) $(COMMON_DIR)/*.template
# Remove trailing numbers (to 99) on stem
TEMPLATE1 = $(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%, \
$(patsubst %4,%,$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%, \
$(patsubst %8,%,$(patsubst %9,%,$*))))))))))
TEMPLATE2 = $(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%, \
$(patsubst %4,%,$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%, \
$(patsubst %8,%,$(patsubst %9,%,$(TEMPLATE1)))))))))))
TEMPLATE3 = $(addsuffix $(TEMPL_SUFFIX),$(addprefix ../,$(TEMPLATE2)))
TEMPLATE_FILENAME = $(firstword $(wildcard $($*_TEMPLATE) \
$(addprefix ../,$($*_TEMPLATE)) ../$*$(TEMPL_SUFFIX) $(TEMPLATE3) \
../template))
TEMPLATE1=$(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%,$(patsubst %4,%, \
$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%,$(patsubst %8,%,$(patsubst %9,%, \
$*))))))))))
TEMPLATE2=$(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%,$(patsubst %4,%, \
$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%,$(patsubst %8,%,$(patsubst %9,%, \
$(TEMPLATE1)))))))))))
TEMPLATE3=$(addsuffix .template,$(addprefix ../,$(TEMPLATE2)))
TEMPLATE_FILENAME=$(firstword $(wildcard $($*_TEMPLATE) $(addprefix ../,$($*_TEMPLATE)) ../$*.template $(TEMPLATE3) ../template))
# dbst based database optimization
ifeq '$(DB_OPT)' 'YES'
RAW=.raw
DBS = $(filter %.db,$(DB)) $(addsuffix $(RAW),$(filter %.db,$(DB)))
COMMON_DBS = $(addprefix $(COMMON_DIR)/,$(DBS))
endif
INSTALL_DB_INSTALLS = $(addprefix $(INSTALL_DB)/,$(notdir $(DB_INSTALLS)))
INSTALL_DBD_INSTALLS = $(addprefix $(INSTALL_DBD)/,$(notdir $(DBD_INSTALLS)))
COMMONDEP_TARGET = $(COMMON_DIR)/$(basename $@)
#---------------------------------------------------------------
# acf files
##################################################### acf files
# An access security configuration file, *.acf, can be created from
# an *.acs file (has format of acf file plus #include "filename" lines)
@@ -125,8 +123,7 @@ ACF_INCLUDES = -I. $(TARGET_INCLUDES) $(USR_INCLUDES)\
ACFDEPENDS_CMD = $(MKMF) -m $@ $(ACF_INCLUDES) $(COMMONDEP_TARGET) $<
ACF_CMD = $(CPP) $(ACF_CPPFLAGS) $(ACF_INCLUDES) $< > $@
#---------------------------------------------------------------
# dependencies
##################################################### dependancies
HINC += $(addsuffix .h,$(DBDINC_NAME))
COMMON_DBDINC += $(addprefix $(COMMON_DIR)/,$(HINC))
@@ -136,12 +133,12 @@ DBDDEPENDS_FILES += $(addsuffix $(DEP),$(HINC) \
$(patsubst $(COMMON_DIR)/%,%, \
$(filter-out $(COMMON_DIR)/bpt%.dbd,$(COMMON_DBDS))))
#---------------------------------------------------------------
#####################################################
ifndef T_A
DEP = .d
TEMPLATE3 += $(addsuffix $(TEMPL_SUFFIX), $(TEMPLATE2))
TEMPLATE3+=$(addsuffix .template, $(TEMPLATE2))
COMMON_DIR = .
INSTALL_DBDS =
@@ -156,13 +153,18 @@ ACTIONS += install
ACTIONS += buildInstall
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
actionArchTargets = $(foreach action, $(ACTIONS), \
$(foreach arch, $(BUILD_ARCHS), $(action)$(DIVIDER)$(arch)))
cleanArchTargets = $(foreach arch, $(BUILD_ARCHS), clean$(DIVIDER)$(arch))
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
cleanArchTargets = $(foreach arch,$(BUILD_ARCHS), clean$(DIVIDER)$(arch))
-include $(TOP)/configure/CONFIG_APP_INCLUDE
all: install
ifeq ($(EPICS_HOST_ARCH),$T_A)
host: install
else
# Do nothing
host:
endif
install: buildInstall
@@ -170,30 +172,20 @@ buildInstall : build
rebuild: clean install
.PHONY: all $(ACTIONS)
.PHONY: all host $(ACTIONS)
$(actionArchTargets) $(BUILD_ARCHS): install
$(cleanArchTargets): clean
.PHONY: $(BUILD_ARCHS) $(actionArchTargets) $(cleanArchTargets)
else
# T_A is defined
ifeq ($(EPICS_HOST_ARCH),$(T_A))
host: install
else
host:
endif
.PHONY: host
endif # T_A
endif # T_A defined
ifneq (,$(strip $(DBDDEPENDS_FILES)))
-include $(DBDDEPENDS_FILES)
endif
#---------------------------------------------------------------
# build dependancies, clean rule
##################################################### build dependancies, clean rule
inc : $(COMMON_INC) $(INSTALL_INC)
@@ -213,8 +205,7 @@ db_clean :
realclean: clean
#---------------------------------------------------------------
# Dependency files
##################################################### Dependency files
%Record.h$(DEP): $(COMMON_DIR)/%Record.dbd
@$(RM) $@
@@ -265,19 +256,19 @@ menu%.h$(DEP): ../menu%.dbd
@$(DBEXPAND) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $($*_DBD) > $@
@echo "$(COMMONDEP_TARGET): ../Makefile" >> $@
%.db$(DEP): %$(SUBST_SUFFIX)
%.db$(RAW)$(DEP): %$(SUBST_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) -S$< $(TEMPLATE_FILENAME) > $@
%.db$(DEP): ../%$(SUBST_SUFFIX)
%.db$(RAW)$(DEP): ../%$(SUBST_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) -S$< $(TEMPLATE_FILENAME) > $@
%.db$(DEP): %$(TEMPL_SUFFIX)
%.db$(RAW)$(DEP): %.template
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) $< > $@
%.db$(DEP): ../%$(TEMPL_SUFFIX)
%.db$(RAW)$(DEP): ../%.template
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) $< > $@
@@ -291,8 +282,14 @@ menu%.h$(DEP): ../menu%.dbd
.PRECIOUS: %$(DEP)
#---------------------------------------------------------------
# Substitution files
##################################################### CapFast filter
$(COMMON_DIR)/%.edf: ../%.sch $(DEPSCHS)
@$(RM) $@
@if [ ! -f cad.rc -a -r ../cad.rc ] ; then ln -s ../cad.rc ; fi
$(SCH2EDIF) $(SCH2EDIF_SYSFLAGS) $(SCH2EDIF_FLAGS) -o $@ $<
##################################################### Substitution files
# WARNING: CREATESUBSTITUTIONS script needs output dir on command line
@@ -313,21 +310,25 @@ $(INSTALL_DB)/%$(SUBST_SUFFIX): ../%$(SUBST_SUFFIX)
.PRECIOUS: $(COMMON_DIR)/%$(SUBST_SUFFIX)
#---------------------------------------------------------------
# Template files
##################################################### Template files
$(INSTALL_DB)/%$(TEMPL_SUFFIX): %$(TEMPL_SUFFIX)
$(COMMON_DIR)/%.template: $(COMMON_DIR)/%.edf
@$(RM) $@
$(E2DB) $(E2DB_SYSFLAGS) $(E2DB_FLAGS) -n $@.VAR $<
@$(REPLACEVAR) < $@.VAR > $@
@$(RM) $@.VAR
$(INSTALL_DB)/%.template: %.template
$(ECHO) "Installing template file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
$(INSTALL_DB)/%$(TEMPL_SUFFIX): ../%$(TEMPL_SUFFIX)
$(INSTALL_DB)/%.template: ../%.template
$(ECHO) "Installing template file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
.PRECIOUS: $(COMMON_DIR)/%$(TEMPL_SUFFIX)
.PRECIOUS: $(COMMON_DIR)/%.template
#---------------------------------------------------------------
# INC files
##################################################### INC files
$(COMMON_DIR)/%Record.h: $(COMMON_DIR)/%Record.dbd
@$(RM) $(notdir $@)
@@ -361,8 +362,7 @@ $(COMMON_DIR)/menu%.h: ../menu%.dbd
.PRECIOUS: $(COMMON_DIR)/%.h
#---------------------------------------------------------------
# DBD files
##################################################### DBD files
$(COMMON_DIR)/bpt%.dbd: bpt%.data
@$(RM) $(notdir $@)
@@ -425,64 +425,56 @@ $(foreach file, $(DBD_INSTALLS), $(eval $(call DBD_INSTALLS_template, $(file))))
.PRECIOUS: $(COMMON_DBDS) $(COMMON_DIR)/%.dbd
#---------------------------------------------------------------
# HTML files
##################################################### HTML files
$(COMMON_DIR)/%.html: %.dbd.pod
$(COMMON_DIR)/%.html: %.dbd.pod $(TOOLS)/dbdToHtml.pl
@$(RM) $(notdir $@)
$(DBDTOHTML) $(DBDFLAGS) -o $(notdir $@) $<
$(PERL) $(TOOLS)/dbdToHtml.pl $(DBDFLAGS) -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.html: %.pod
$(COMMON_DIR)/%.html: %.pod $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PODTOHTML) -o $(notdir $@) $<
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.html: %.pm
$(COMMON_DIR)/%.html: %.pm $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PODTOHTML) -o $(notdir $@) $<
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.html: ../%.pm
$(COMMON_DIR)/%.html: ../%.pm $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PODTOHTML) -s -o $(notdir $@) $<
@$(MKDIR) $(dir $@)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.html: ../%.pl
@$(RM) $(notdir $@)
$(PODTOHTML) -s -o $(notdir $@) $<
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
.PRECIOUS: $(COMMON_DIR)/%.html %.html
#---------------------------------------------------------------
# DB files
##################################################### DB files
$(COMMON_DIR)/%.db: $(COMMON_DIR)/%.edf
$(COMMON_DIR)/%.db$(RAW): $(COMMON_DIR)/%.edf
$(E2DB) $(E2DB_SYSFLAGS) $(E2DB_FLAGS) -n $*.VAR $<
@$(REPLACEVAR) < $*.VAR > $@
@$(RM) $*.VAR
$(COMMON_DIR)/%.db: %$(SUBST_SUFFIX)
$(COMMON_DIR)/%.db$(RAW): %$(SUBST_SUFFIX)
$(ECHO) "Inflating database from $< $(TEMPLATE_FILENAME)"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) -S$< $(TEMPLATE_FILENAME)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db: ../%$(SUBST_SUFFIX)
$(COMMON_DIR)/%.db$(RAW): ../%$(SUBST_SUFFIX)
$(ECHO) "Inflating database from $< $(TEMPLATE_FILENAME)"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) -S$< $(TEMPLATE_FILENAME)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db: %$(TEMPL_SUFFIX)
$(COMMON_DIR)/%.db$(RAW): %.template
$(ECHO) "Inflating database from $<"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db: ../%$(TEMPL_SUFFIX)
$(COMMON_DIR)/%.db$(RAW): ../%.template
$(ECHO) "Inflating database from $<"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) $<
@@ -500,6 +492,22 @@ $(COMMON_DIR)/%.acf: ../%.acs
.PRECIOUS: $(COMMON_DIR)/%.acf
# dbst based database optimization
ifeq '$(DB_OPT)' 'YES'
$(COMMON_DIR)/%.db$(RAW): ../%.db
@$(RM) $@
$(CP) $< $@
$(COMMON_DIR)/%.db: $(COMMON_DIR)/%.db$(RAW)
$(ECHO) "Optimizing database $@"
@$(RM) $@
$(DBST) . $< -d > $@
.PRECIOUS: $(COMMON_DIR)/%.db
.PRECIOUS: $(DB:%=$(COMMON_DIR)/%$(RAW))
else
$(INSTALL_DB)/%: %
$(ECHO) "Installing $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
@@ -507,6 +515,7 @@ $(INSTALL_DB)/%: %
$(INSTALL_DB)/%: ../%
$(ECHO) "Installing $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
endif
$(INSTALL_DB)/%.db: $(COMMON_DIR)/%.db
$(ECHO) "Installing created db file $@"
@@ -522,8 +531,8 @@ $(foreach file, $(DB_INSTALLS), $(eval $(call DB_INSTALLS_template, $(file))))
.PRECIOUS: $(COMMON_DIR)/%.edf
.PRECIOUS: $(COMMON_DBS)
#---------------------------------------------------------------
# register record,device,driver support
##################################################### register record,device,driver support
%_registerRecordDeviceDriver.cpp: $(COMMON_DIR)/%.dbd
@$(RM) $@
@@ -539,3 +548,4 @@ $(foreach file, $(DB_INSTALLS), $(eval $(call DB_INSTALLS_template, $(file))))
.PRECIOUS: %_registerRecordDeviceDriver.cpp
##################################################### END OF FILE

View File

@@ -102,6 +102,7 @@ endif
# Products and Object libraries
#
PRODTARGETS += $(PRODNAME) $(MUNCHNAME) $(CTDT_SRCS) $(CTDT_OBJS) $(NMS)
TESTPRODTARGETS += $(TESTPRODNAME) $(TESTMUNCHNAME)
#---------------------------------------------------------------
# Test specifications and test result files
@@ -140,7 +141,7 @@ rebuild: clean install
build: inc
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODNAME) \
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODTARGETS) \
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
inc : $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS)
@@ -158,20 +159,21 @@ clean: build_clean
build_clean:
$(ECHO) "Cleaning"
@$(RM) *.i *$(OBJ) *.a $(TESTPRODNAME) \
@$(RM) *.i *$(OBJ) *.a \
$(LIBNAME) $(TESTLIBNAME) $(SHRLIBNAME) $(TESTSHRLIBNAME) \
$(DLLSTUB_LIBNAME) $(TESTDLLSTUB_LIBNAME) \
$(LOADABLE_SHRLIBNAME) \
$(INC) $(TARGETS) $(TDS) $(CLEANS) \
*.out MakefileInclude *.manifest *.exp \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) $(TESTPRODTARGETS) \
$(TESTSCRIPTS) $(TAPFILES) $(JUNITFILES)
ifdef RES
@$(RM) *$(RES)
endif
$(DIRECTORY_TARGETS) :
$(MKDIR) $@
# Sort mkdir targets to remove duplicates & make parents first
$(DIRECTORY_TARGETS):
$(MKDIR) $(sort $@)
# Install LIB_INSTALLS libraries before linking executables
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS)
@@ -254,15 +256,13 @@ YACCOPT ?= $($*_YACCOPT)
$(MV) $*.tab.c $*.c
$(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,)
# must be a seperate rule since when not using '-d' the
# must be a separate rule since when not using '-d' the
# prefix for .h will be different then .c
%.h : %.c %.y
%.c: %.l
@$(RM) $*.yy.c
$(LEX) $(LEXOPT) -t $< > $*.yy.c
@$(RM) $@
$(MV) $*.yy.c $@
$(LEX) $(LEXOPT) -o$@ $<
#---------------------------------------------------------------
# Libraries, shared/DLL and stubs
@@ -321,6 +321,10 @@ $(MUNCHNAME): %$(MUNCH_SUFFIX): $(MUNCH_DEPENDS) %$(EXE)
@$(RM) $@
$(MUNCH_CMD)
$(TESTMUNCHNAME): %$(MUNCH_SUFFIX): $(MUNCH_DEPENDS) %$(EXE)
@$(RM) $@
$(MUNCH_CMD)
#---------------------------------------------------------------
# GeSys modules for RTEMS
$(MODNAME): %$(MODEXT): %$(EXE)
@@ -328,12 +332,6 @@ $(MODNAME): %$(MODEXT): %$(EXE)
@$(RM) $@
$(LINK.mod)
#---------------------------------------------------------------
# Generate Perl include path module
%ModuleDirs.pm: $(wildcard $(TOP)/configure/RELEASE*)
@$(MKDIR) $(dir $@)
$(CONVERTRELEASE) -T $(TOP) $@
#---------------------------------------------------------------
# Automated testing
@@ -380,7 +378,7 @@ endif
# If there's a perl test script (.plt) available, use it
%.t: ../%.plt
@$(RM) $@
$(EXPAND_TOOL) -t $(INSTALL_LOCATION) -a $(T_A) $< $@
$(CP) $< $@
# Test programs (.t files) must be written in Perl.
# Generate a perl program to exec the real test binary.
@@ -388,14 +386,6 @@ endif
@$(RM) $@
$(PERL) $(TOOLS)/makeTestfile.pl $@ $<
#---------------------------------------------------------------
# Generate header with version number from VCS
ifneq ($(GENVERSION),)
$(COMMON_DIR)/$(GENVERSION): FORCE
$(GENVERSIONHEADER) -t $(TOP) -N $(GENVERSIONMACRO) -V "$(GENVERSIONDEFAULT)" $@
endif
#---------------------------------------------------------------
# Install rules for BIN_INSTALLS and LIB_INSTALLS
@@ -471,7 +461,6 @@ ifneq (,$(strip $(LOADABLE_SHRLIB_VERSION)))
endif # LOADABLE_SHRLIB_VERSION
endif # LOADABLE_SHRLIB_SUFFIX
ifneq ($(INSTALL_CONFIGS),)
$(INSTALL_CONFIG)/%: %
$(ECHO) "Installing config file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
@@ -479,7 +468,6 @@ $(INSTALL_CONFIG)/%: %
$(INSTALL_CONFIG)/%: ../%
$(ECHO) "Installing config file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
endif
$(INSTALL_INCLUDE)/% : $(COMMON_DIR)/%
$(ECHO) "Installing generated generic include file $@"
@@ -532,7 +520,7 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
.PHONY: all host inc build install clean rebuild buildInstall build_clean
.PHONY: runtests tapfiles clean-tests test-results junitfiles
.PHONY: checkRelease warnRelease noCheckRelease FORCE
.PHONY: checkRelease warnRelease noCheckRelease
endif # BASE_RULES_BUILD
# EOF RULES_BUILD

View File

@@ -38,6 +38,17 @@ $(foreach target, $(PROD) $(TESTPROD), \
#-----------------------------------------------------------------------
# These must be done before PROD2_template
define TESTLIBRARY_template
$(1)_DIR = .
TESTBUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)
endef
$(foreach target, $(TESTLIBRARY), \
$(eval $(call TESTLIBRARY_template,$(strip $(target)))))
#-----------------------------------------------------------------------
define TARGET2_template
$(1)_LDLIBS += $$($(1)_LIBS)
$(1)_LDLIBS += $$(if $$(strip $$($(1)_LIBS_$(OS_CLASS))), \
@@ -123,16 +134,6 @@ $(foreach target, $(LIBRARY), \
#-----------------------------------------------------------------------
define LIBRARY3_template
$(1)_DIR = .
TESTBUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)
endef
$(foreach target, $(TESTLIBRARY), \
$(eval $(call LIBRARY3_template,$(strip $(target)))))
#-----------------------------------------------------------------------
define LOADABLE_LIBRARY_template
LOADABLE_BUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)

View File

@@ -21,9 +21,6 @@ realuninstall: uninstallDirs
UNINSTALL_DIRS += $(INSTALL_DBD) $(INSTALL_INCLUDE) $(INSTALL_DOC) \
$(INSTALL_HTML) $(INSTALL_TEMPLATES) $(INSTALL_DB) $(DIRECTORY_TARGETS)
ifneq ($(INSTALL_LOCATION),$(TOP))
UNINSTALL_DIRS += $(INSTALL_CONFIG)
endif
uninstallDirs:
$(RMDIR) $(UNINSTALL_DIRS)

View File

@@ -136,6 +136,13 @@ MOD_LDFLAGS = $(OPT_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(POSIX_LDFLAGS) \
LINK.mod = $(CCC) -o $@ $(PRODDIR_LDFLAGS) $(MOD_LDFLAGS)
LINK.mod += $(PROD_LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(MOD_LDLIBS)
#--------------------------------------------------
# Here munching means creating a bootable object binary
ifdef MUNCH_SUFFIX
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
TESTMUNCHNAME = $(TESTPRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
endif
#--------------------------------------------------
# RTEMS has neither shared libraries nor dynamic loading
STATIC_BUILD=YES

View File

@@ -15,7 +15,6 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -13,7 +13,6 @@ ARCH_DEP_CFLAGS += -DHAVE_PPCBUG
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems
gzip -f9 rtems

View File

@@ -7,7 +7,6 @@ ARCH_DEP_CFLAGS += -DHAVE_PPCBUG
ARCH_DEP_CFLAGS += -DNVRAM_INDIRECT
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems
gzip -f9 rtems

View File

@@ -15,7 +15,6 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -16,7 +16,6 @@ ARCH_DEP_CFLAGS += -DBSP_NVRAM_BASE_ADDR=0xf1110000
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -8,7 +8,6 @@
RTEMS_TARGET_CPU=i386
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< temp.bin
$(BIN2BOOT) $@ 0x00097E00 \

View File

@@ -9,7 +9,6 @@ RTEMS_TARGET_CPU = m68k
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@
endef

View File

@@ -1,7 +1,7 @@
# CONFIG.Common.vxWorksCommon
#
# Definitions for vxWorks target archs
# Override these definitions in CONFIG_SITE.Common.vxWorksCommon
# Sites may override these definitions in CONFIG_SITE.Common.vxWorksCommon
# or CONFIG_SITE.<host>.vxWorksCommon
#-------------------------------------------------------
@@ -63,6 +63,8 @@ VXWORKS_MAJOR_VERSION = $(basename $(basename $(VXWORKS_VERSION)))
# These are needed for vxWorks 6.x; the GNU toolset version number
# is in the path to the compiler tools:
VX_GNU_VERSION_5.4 = 2.95
VX_GNU_VERSION_5.5 = 2.96
VX_GNU_VERSION_6.0 = 3.3.2
VX_GNU_VERSION_6.1 = 3.3.2
VX_GNU_VERSION_6.2 = 3.3.2
@@ -78,21 +80,30 @@ VX_GNU_VERSION = $(VX_GNU_VERSION_$(VXWORKS_VERSION))
VX_GNU_MAJOR_VERSION = $(basename $(basename $(VX_GNU_VERSION)))
#--------------------------------------------------
# Fix old Linux WIND_HOST_TYPE
# Fix WIND_BASE for vxWorks 6.x on linux
# NB: We know the value of WIND_HOST_TYPE here, but not VXWORKS_VERSION
ifeq ($(WIND_HOST_TYPE),x86-linux)
WIND_HOST_TYPE = x86-linux2
WIND_HOST_TYPE_5 = x86-linux
WIND_HOST_TYPE_6 = x86-linux2
WIND_HOST_TYPE = $(WIND_HOST_TYPE_$(VXWORKS_MAJOR_VERSION))
endif
#--------------------------------------------------
# vxWorks directory definitions
VX_DIR = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
VX_DIR_5 = $(WIND_BASE)
VX_DIR_6 = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
VX_DIR = $(VX_DIR_$(VXWORKS_MAJOR_VERSION))
GNU_TARGET_INCLUDE_DIR = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
VX_INCLUDE_DIRS_5 = $(VX_DIR)/target/h
VX_INCLUDE_DIRS_6 = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
GNU_TARGET_INCLUDE_DIR = $(VX_INCLUDE_DIRS_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# vxWorks GNU directories
GNU_DIR = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
GNU_DIR_5 = $(WIND_BASE)/host/$(WIND_HOST_TYPE)
GNU_DIR_6 = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# This finds nm on any supported VxWorks version
@@ -102,7 +113,9 @@ NM = $(firstword $(wildcard $(WIND_BASE)/*/$(WIND_HOST_TYPE)/bin/$(NMPROG)))
#--------------------------------------------------
# A linker script is essential for munching from vxWorks 6.6 onwards
# (i.e. with versions that use gcc 4.1.2 or later).
# (i.e. with versions that use gcc 4.1.2 or later). It can be used
# with any vxWorks 5 or 6 version, but apparently should not be used
# when compiling for 68K (which isn't supported in vxWorks 6 anyway)
MUNCH_LDFLAGS_6 = -T $(VX_DIR)/target/h/tool/gnu/ldscripts/link.OUT
MUNCH_LDFLAGS = $(MUNCH_LDFLAGS_$(VXWORKS_MAJOR_VERSION))
@@ -118,10 +131,11 @@ export TOOL_FAMILY = GNU
OP_SYS_CPPFLAGS += -DvxWorks=vxWorks
OP_SYS_CFLAGS += -fno-builtin
# Fix for vxWorks headers that use macros defined in vxWorks.h but
# Fix for vxWorks 5 headers that use macros defined in vxWorks.h but
# which don't actually include vxWorks.h themselves, for example the
# target/h/sys/stat.h file which uses ULONG. This also stops dbDefs.h
# from defining the OFFSET macro, which generates lots of warnings.
# from defining the OFFSET macro, which generates lots of warnings in
# both vxWorks 5 and 6.
OP_SYS_INCLUDE_CPPFLAGS += -include $(VX_DIR)/target/h/vxWorks.h
#--------------------------------------------------
@@ -134,6 +148,7 @@ OPT_CXXFLAGS_YES = -O2
CODE_CFLAGS =
#
# For vxWorks versions before 6.3 we need this g++ compiler flag
CODE_CXXFLAGS_5 = -fno-implicit-templates
CODE_CXXFLAGS_6.0 = -fno-implicit-templates
CODE_CXXFLAGS_6.1 = -fno-implicit-templates
CODE_CXXFLAGS_6.2 = -fno-implicit-templates

View File

@@ -8,7 +8,7 @@
CP = cp
MV = mv
RM = rm -f
MKDIR = mkdir -p
MKDIR = mkdir
RMDIR = rm -rf
CAT = cat

View File

@@ -65,14 +65,14 @@ GNU = NO
#
# Darwin shared libraries
#
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
SHRLIB_LDFLAGS = -dynamiclib -undefined dynamic_lookup \
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
$(addprefix -compatibility_version , $(SHRLIB_VERSION)) \
$(addprefix -current_version , $(SHRLIB_VERSION))
SHRLIB_SUFFIX_BASE = .dylib
SHRLIB_SUFFIX = $(addprefix ., $(SHRLIB_VERSION))$(SHRLIB_SUFFIX_BASE)
LOADABLE_SHRLIB_LDFLAGS = -bundle -flat_namespace -undefined suppress
LOADABLE_SHRLIB_LDFLAGS = -bundle -undefined dynamic_lookup
#
# Position-independent code is the default on Darwin.

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux2
WIND_HOST_TYPE = x86-linux

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux2
WIND_HOST_TYPE = x86-linux

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux2
WIND_HOST_TYPE = x86-linux

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux2
WIND_HOST_TYPE = x86-linux

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux2
WIND_HOST_TYPE = x86-linux

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux2
WIND_HOST_TYPE = x86-linux

View File

@@ -79,16 +79,20 @@ CPP = cl -nologo -C -E
# Configure OS vendor C++ compiler
#
# __STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
# -EHsc - generate code for exceptions
# -GR - generate code for run time type identification
#
CCC = cl -EHsc -GR
CODE_CPPFLAGS += -nologo -D__STDC__=0
# Other compiler flags, used for CPP, C and C++
#
# -FC - Show absolute path of source file in diagnostics
# -D__STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
@@ -136,6 +140,16 @@ STATIC_LDLIBS_NO=
STATIC_LDFLAGS=
RANLIB=
#
# option needed for parallel builds with Visual Studio 2015 onward
#
# -FS Force Synchronous PDB Writes
ifneq ($(VisualStudioVersion),)
OPT_CXXFLAGS_NO += -FS
OPT_CFLAGS_NO += -FS
endif
#
# add -profile here to run the ms profiler
# -LTCG whole program optimization

View File

@@ -1,13 +1,21 @@
# CONFIG_SITE.Common.vxWorksCommon
#
# Site specific definitions for vxWorks target builds.
# Only the local epics system manager should modify this file
# Compiler options can vary with the vxWorks version number, so we
# need to know that. Do not include any third-level digits.
# need to know that. However don't include any third-level digits
# (e.g. the .2 in 5.5.2) because we don't need them.
# Note: vxWorks 5.4.x and 5.5.x (Tornado 2.x) are not supported.
# VxWorks 6.0 through 6.5 use older, untested versions of GCC.
# Note: vxWorks 5.4.x (Tornado 2.0.x) is not supported
#VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.0
#VXWORKS_VERSION = 6.1
#VXWORKS_VERSION = 6.2
#VXWORKS_VERSION = 6.3
#VXWORKS_VERSION = 6.4
#VXWORKS_VERSION = 6.5
#VXWORKS_VERSION = 6.6
#VXWORKS_VERSION = 6.7
#VXWORKS_VERSION = 6.8
@@ -19,6 +27,7 @@ VXWORKS_VERSION = 6.9
# CONFIG_SITE.$(EPICS_HOST_ARCH).vxWorksCommon file.
# WIND_BASE is where you installed the Wind River software.
# Under vxWorks 6.x this is *not* the same as the old VX_DIR setting
#WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)

View File

@@ -14,10 +14,10 @@
#GNU_DIR = /usr/local
# Different distribution cross-build packages use different prefixes:
# Ubuntu, RHEL7:
CMPLR_PREFIX = i686-w64-mingw32-
# RHEL6:
#CMPLR_PREFIX = i686-pc-mingw32-
# Ubuntu:
#CMPLR_PREFIX = i686-w64-mingw32-
# RHEL:
CMPLR_PREFIX = i686-pc-mingw32-
# Debian?
#CMPLR_PREFIX = i586-mingw32msvc-

View File

@@ -4,37 +4,25 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Known Problems in Base-3.16.1</title>
<title>Known Problems in R3.15.6</title>
</head>
<body>
<h1 style="text-align: center">EPICS Base R3.16.1: Known Problems</h1>
<h1 style="text-align: center">EPICS Base R3.15.6: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-3.16.1 tree. Download them, then use the GNU Patch program as
base-3.15.6 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.16.1</b>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.6</b>
% <b>patch -p1 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following problems were known by the developers at the time of this
release:</p>
<p>The following significant problems have been reported with this
version of EPICS Base:</p>
<ul>
<!-- Items added after release should be formatted thusly:
<li>YYYY-MM-DD: Description of problem.
<a href="fix.patch">This patch</a> fixes the problem.
...</li>
-->
<li>IOCs running on some versions of Cygwin may display warnings at iocInit
about duplicate EPICS CA Address list entries. These warnings might be due
to a bug in Cygwin; they are benign and can be ignored.</li>
<li>64-bit Windows builds of the CAS library may not work with some compilers.
The code in <tt>src/legacy/gdd</tt> is incompatible with the LLP64 model
that Windows uses for its 64-bit ABI.</li>
<li>None known as yet.</li>
</ul>

View File

@@ -1,24 +1,24 @@
Installation Instructions
EPICS Base Release 3.16.1
EPICS Base Release 3.15.6
--------------------------------------------------------------------------
Table of Contents
* What is EPICS base?
* What is new in this release?
* Copyright
* Supported platforms
* Supported compilers
* Software requirements
* Host system storage requirements
* Documentation
* Directory Structure
* Build related components
* Building EPICS base (Unix and Win32)
* Example application and extension
* Multiple host platforms
* What is EPICS base?
* What is new in this release?
* Copyright
* Supported platforms
* Supported compilers
* Software requirements
* Host system storage requirements
* Documentation
* Directory Structure
* Build related components
* Building EPICS base (Unix and Win32)
* Example application and extension
* Multiple host platforms
--------------------------------------------------------------------------
@@ -85,17 +85,17 @@
as processes on the host platform.
vxWorks
You must have vxWorks 6 installed if any of your target systems are
vxWorks systems; the C++ compilers for vxWorks 5.x are now too old to
support. The vxWorks installation provides the cross-compiler and header
files needed to build for these targets. The absolute path to and the
version number of the vxWorks installation must be set in the
You must have vxWorks 5.5.x or 6.x installed if any of your target
systems are vxWorks systems; the C++ compiler for vxWorks 5.4 is now too
old to support. The vxWorks installation provides the cross-compiler and
header files needed to build for these targets. The absolute path to and
the version number of the vxWorks installation must be set in the
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.
Consult the vxWorks 6.x EPICS web pages and the vxWorks documentation
for information about configuring your vxWorks operating system for use
with EPICS.
Consult the vxWorks 5.x or vxWorks 6.x EPICS web pages about and the
vxWorks documentation for information about configuring your vxWorks
operating system for use with EPICS.
RTEMS
For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or
@@ -166,12 +166,11 @@
base/startup directory - contains scripts to set environment and path
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
Site.profile bourne shell script to set path and env variables
Site.cshrc c shell script to set path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
win32.bat WIN32 bat file to set path and env variables
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
unix.csh C shell script to set path and env variables
unix.sh Bourne shell script to set path and env variables
win32.bat Bat file example to configure win32-x86 target
windows.bat Bat file example to configure windows-x64 target
base/configure directory - contains build definitions and rules

View File

@@ -21,7 +21,7 @@ of my Bash login script (~/.bash_login):
#
EPICS_BASE="${HOME}/src/EPICS/base"
EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
<strong>.</strong> "${EPICS_BASE}"/startup/Site.profile
<strong>.</strong> "${EPICS_BASE}"/startup/unix.sh
</pre>
</li>
<li>

View File

@@ -9,7 +9,7 @@
<BODY>
<CENTER>
<H1>Installation Instructions</H1>
<H2>EPICS Base Release 3.16.1</H2><BR>
<H2>EPICS Base Release 3.15.6</H2><BR>
</CENTER>
<HR>
<H3> Table of Contents</H3>
@@ -90,16 +90,17 @@
as processes on the host platform.</P>
<P><B>vxWorks</B><BR>
You must have vxWorks 6 installed if any of your target systems are vxWorks
systems; the C++ compilers for vxWorks 5.x are now too old to support. The
vxWorks installation provides the cross-compiler and header files needed to
You must have vxWorks 5.5.x or 6.x installed if any of your target systems are
vxWorks systems; the C++ compiler for vxWorks 5.4 is now too old to support.
The vxWorks installation provides the cross-compiler and header files needed to
build for these targets. The absolute path to and the version number of the
vxWorks installation must be set in the
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.</P>
<P>Consult the <a href="http://www.aps.anl.gov/epics/base/vxWorks6.php">vxWorks
6.x</a> EPICS web pages and the vxWorks documentation for information
<P>Consult the <a href="https://epics.anl.gov/base/tornado.php">vxWorks
5.x</a> or <a href="https://epics.anl.gov/base/vxWorks6.php">vxWorks
6.x</a> EPICS web pages about and the vxWorks documentation for information
about configuring your vxWorks operating system for use with EPICS.</P>
<P><B>RTEMS</B><BR>
@@ -128,7 +129,7 @@
<H3><A NAME="0_0_8"> Documentation</A></H3>
<BLOCKQUOTE>EPICS documentation is available through the
<a href="http://www.aps.anl.gov/epics/">EPICS website</a> at Argonne.
<a href="https://epics.anl.gov/">EPICS website</a> at Argonne.
<P>Release specific documentation can also be found in the base/documentation
directory of the distribution.</BLOCKQUOTE>
@@ -176,12 +177,11 @@
<H4>base/startup directory - contains scripts to set environment and path</H4>
<PRE>
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
Site.profile bourne shell script to set path and env variables
Site.cshrc c shell script to set path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
win32.bat WIN32 bat file to set path and env variables
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
unix.csh C shell script to set path and env variables
unix.sh Bourne shell script to set path and env variables
win32.bat Bat file example to configure win32-x86 target
windows.bat Bat file example to configure windows-x64 target
</PRE>
<H4>base/configure directory - contains build definitions and rules</H4>
@@ -190,12 +190,12 @@
CONFIG.CrossCommon Cross build definitions
CONFIG.gnuCommon Gnu compiler build definitions for all archs
CONFIG_ADDONS Definitions for &lt;osclass&gt; and DEFAULT options
CONFIG_APP_INCLUDE
CONFIG_APP_INCLUDE
CONFIG_BASE EPICS base tool and location definitions
CONFIG_BASE_VERSION Definitions for EPICS base version number
CONFIG_COMMON Definitions common to all builds
CONFIG_ENV Definitions of EPICS environment variables
CONFIG_FILE_TYPE
CONFIG_FILE_TYPE
CONFIG_SITE Site specific make definitions
CONFIG_SITE_ENV Site defaults for EPICS environment variables
MAKEFILE Installs CONFIG* RULES* creates
@@ -206,9 +206,9 @@
RULES_ARCHS Definitions and rules for building architectures
RULES_BUILD Build and install rules and definitions
RULES_DIRS Definitions and rules for building subdirectories
RULES_EXPAND
RULES_FILE_TYPE
RULES_TARGET
RULES_EXPAND
RULES_FILE_TYPE
RULES_TARGET
RULES_TOP Rules specific to a &lt;top&gt; dir (uninstall and tar)
Sample.Makefile Sample makefile with comments
</PRE>
@@ -340,7 +340,7 @@ Files in the base/startup directory have been provided to
<H3><A NAME="0_0_13"> Example application and extension</A></H3>
<BLOCKQUOTE>A perl tool, makeBaseApp.pl is included in the distribution
file. This script will create a sample application that can be built
and then executed to try out this release of base.
and then executed to try out this release of base.
<P>
Instructions for building and executing the 3.15 example application
@@ -350,8 +350,8 @@ Files in the base/startup directory have been provided to
create and build an example application in a user created &lt;top&gt;
directory. It also explains how to run the example application on a
vxWorks ioc or as a process on the host system.
By running the example application as a host-based IOC, you will be
able to quickly implement a complete EPICS system and be able to run channel
By running the example application as a host-based IOC, you will be
able to quickly implement a complete EPICS system and be able to run channel
access clients on the host system.
<P>

File diff suppressed because it is too large Load Diff

View File

@@ -33,27 +33,29 @@
<h1>EPICS Base Release Procedures &amp; Checklist</h1>
<p>This document describes the procedures and provides a checklist of tasks
that should be performed when creating production releases of EPICS Base.</p>
that should be performed when creating new releases of EPICS Base.</p>
<h3>The Release Process</h3>
<p>The version released on the Feature Freeze date is designated the first
pre-release, <tt>-pre1</tt>. The first release candidate <tt>-rc1</tt> is the
pre-release, <tt>-pre1</tt>. The first Release Candidate <tt>-rc1</tt> is the
first version that has undergone widespread testing and which has no known
problems in it that are slated to be fixed in this release. New versions should
be made at about weekly intervals during the testing and debugging period, and
will be designated as either pre-release or release candidate versions by the
Release Manager. After a release candidate has been available to the whole
be made at 2-weekly intervals during the testing and debugging period, and will
be designated as either pre-release versions or Release Candidates by the
Release Manager. After a Release Candidate has been available to the whole
community for testing for at least a week without any additional problems being
reported or significant changes being committed, the branch can be designated as
the final release version.</p>
<h3>Roles</h3>
<p>The following roles are used below:</p>
<p>The following roles are required. The individuals named here have have been
responsible for these tasks in the past and are expected to continue in the
relevent roles unless the Release Manager designates otherwise:</p>
<dl>
<dt><strong>Release Manager</strong> ()</dt>
<dt><strong>Release Manager</strong> (Ralph Lange)</dt>
<dd>Responsible for managing and tagging the release</dd>
<dt><strong>Platform Developers</strong> (optional)</dt>
<dd>Responsible for individual operating system platforms</dd>
@@ -131,40 +133,36 @@ the final release version.</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Git using these tag conventions:
<td>Tag the module in Git, using these tag conventions:
<ul>
<li>
<tt>R3.16.1-pre<i>n</i></tt>
<tt>R3.15.6-pre1</tt>
&mdash; pre-release tag
</li>
<li>
<tt>R3.16.1-rc<i>n</i></tt>
<tt>R3.15.6-rc1</tt>
&mdash; release candidate tag
</li>
</ul>
<blockquote><tt>
cd base-3.16<br />
git tag -m 'ANJ: Tagged for 3.16.1-rc1' R3.16.1-rc1
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6-rc1' R3.15.6-rc1
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Export the tagged version into a tarfile. This command generates a
gzipped tarfile directly from the repository, excluding those files and
directories needed only for continuous integration:
<td>Export the tagged version into a tarfile. The <tt>make-tar.sh</tt>
script generates a gzipped tarfile directly from the tag, excluding the
files and directories that are only used for continuous integration:
<blockquote><tt>
cd base-3.16<br />
git archive
--prefix=base-3.16.1-rc1/
--output=../base-3.16.1-rc1.tar.gz
R3.16.1-rc1
configure documentation LICENSE Makefile README src startup
cd base-3.15<br />
git archive --prefix=base-3.15.6-rc1/ R3.15.6-rc1 --output=base-3.15.6-rc1.tar.gz
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.16.1-rc1.tar.gz
gpg --armor --sign --detach-sig base-3.15.6-rc1.tar.gz
</tt></blockquote>
</td>
</tr>
@@ -258,7 +256,7 @@ the final release version.</p>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Obtain a positive <q>Ok to release</q> from all platform developers
once a release candidate version has gone a whole week without any
once a Release Candidate version has gone a whole week without any
issues being reported.</td>
</tr>
<tr>
@@ -275,28 +273,23 @@ the final release version.</p>
<td>Release Manager</td>
<td>Tag the module in Git:
<blockquote><tt>
cd base-3.16<br />
git tag -m 'ANJ: Tagged for 3.16.1' R3.16.1</i>
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6' R3.15.6
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Export the tagged version into a tarfile. This command generates a
gzipped tarfile directly from the repository, excluding those files and
directories needed only for continuous integration:
<td>Export the tagged version into a tarfile. Note that this command
generates a gzipped tarfile directly from the repository:
<blockquote><tt>
cd base-3.16<br />
git archive
--prefix=base-3.16.1/
--output=../base-3.16.1.tar.gz
R3.16.1
configure documentation LICENSE Makefile README src startup
cd base-3.15<br />
git archive --prefix=base-3.15.6/ R3.15.6 --output=base-3.15.6.tar.gz
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.16.1.tar.gz
gpg --armor --sign --detach-sig base-3.15.6.tar.gz
</tt></blockquote>
</td>
</tr>

View File

@@ -1,51 +0,0 @@
#*************************************************************************
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
TOP = ..
include $(TOP)/configure/CONFIG
# Submodules for bundle build
SUBMODULES += libcom
SUBMODULES += ca
ca_DEPEND_DIRS = libcom
SUBMODULES += database
database_DEPEND_DIRS = ca
SUBMODULES += pvData
pvData_DEPEND_DIRS = libcom
SUBMODULES += pvAccess
pvAccess_DEPEND_DIRS = pvData database
SUBMODULES += normativeTypes
normativeTypes_DEPEND_DIRS = pvData
SUBMODULES += pvaClient
pvaClient_DEPEND_DIRS = pvAccess normativeTypes
SUBMODULES += pvDatabase
pvDatabase_DEPEND_DIRS = pvAccess
SUBMODULES += pva2pva
pva2pva_DEPEND_DIRS = pvAccess
SUBMODULES += example
example_DEPEND_DIRS = pva2pva pvaClient
# Add any checked-out submodules to DIRS
DIRS += $(subst /,,$(dir $(wildcard $(addsuffix /Makefile, $(SUBMODULES)))))
include $(TOP)/configure/RULES_DIRS
# Ensure that RELEASE.local exists before doing anything else
all host $(DIRS) $(ARCHS) $(ACTIONS) $(dirActionTargets) $(dirArchTargets) \
$(dirActionArchTargets) $(actionArchTargets): | RELEASE.local
RELEASE.local:
@echo EPICS_BASE = $(abspath $(INSTALL_LOCATION))> $@
realclean:
$(RM) RELEASE.local

Submodule modules/ca deleted from 5dfd1fc0f0

Submodule modules/database deleted from 73c7b8224d

Submodule modules/libcom deleted from ea7802a838

Submodule modules/pvAccess deleted from ba3b777978

Submodule modules/pvData deleted from 7196658166

Submodule modules/pva2pva deleted from 413102a4bc

View File

@@ -4,7 +4,7 @@
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
# in the file LICENSE that is included with this distribution.
#*************************************************************************
TOP = ..
@@ -12,10 +12,69 @@ include $(TOP)/configure/CONFIG
DIRS += tools
DIRS += tools/test
tools/test_DEPEND_DIRS = tools
DIRS += template/base
template/base_DEPEND_DIRS = tools
DIRS += template/ext
template/ext_DEPEND_DIRS = tools
# Common
DIRS += libCom
libCom_DEPEND_DIRS = tools
DIRS += libCom/RTEMS
libCom/RTEMS_DEPEND_DIRS = libCom
DIRS += libCom/test
libCom/test_DEPEND_DIRS = libCom/RTEMS
# Channel Access
DIRS += ca/client
ca/client_DEPEND_DIRS = libCom
DIRS += ca/client/tools
ca/client/tools_DEPEND_DIRS = ca/client
DIRS += ca/legacy/gdd
ca/legacy/gdd_DEPEND_DIRS = ca/client
DIRS += ca/legacy/pcas
ca/legacy/pcas_DEPEND_DIRS = ca/legacy/gdd
DIRS += ca/legacy/pcas/ex
# needs ioc for dbStaticHost
ca/legacy/pcas/ex_DEPEND_DIRS = ca/legacy/pcas libCom ioc
DIRS += ca/client/perl
ca/client/perl_DEPEND_DIRS = ca/client
# PDB Core
DIRS += ioc
ioc_DEPEND_DIRS = libCom ca/client
DIRS += ioc/db/test
ioc/db/test_DEPEND_DIRS = ioc libCom/RTEMS
DIRS += ioc/dbtemplate/test
ioc/dbtemplate/test_DEPEND_DIRS = ioc
# PDB Standard Record Definitions
DIRS += std
std_DEPEND_DIRS = ioc libCom/RTEMS
DIRS += std/filters/test
std/filters/test_DEPEND_DIRS = std
DIRS += std/rec/test
std/rec/test_DEPEND_DIRS = std
include $(TOP)/configure/RULES_DIRS

308
src/ca/client/CASG.cpp Normal file
View File

@@ -0,0 +1,308 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Jeffrey O. Hill
*/
#include <string>
#include <stdexcept>
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "errlog.h"
#define epicsExportSharedSymbols
#include "iocinf.h"
#include "syncGroup.h"
#include "oldAccess.h"
#include "cac.h"
#include "sgAutoPtr.h"
CASG::CASG ( epicsGuard < epicsMutex > & guard, ca_client_context & cacIn ) :
client ( cacIn ), magic ( CASG_MAGIC )
{
client.installCASG ( guard, *this );
}
CASG::~CASG ()
{
}
void CASG::destructor (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
if ( this->verify ( guard ) ) {
this->reset ( cbGuard, guard );
this->client.uninstallCASG ( guard, *this );
this->magic = 0;
}
else {
this->printFormated ( "cac: attempt to destroy invalid sync group ignored\n" );
}
this->~CASG ();
}
bool CASG::verify ( epicsGuard < epicsMutex > & ) const
{
return ( this->magic == CASG_MAGIC );
}
/*
* CASG::block ()
*/
int CASG::block (
epicsGuard < epicsMutex > * pcbGuard,
epicsGuard < epicsMutex > & guard,
double timeout )
{
epicsTime cur_time;
epicsTime beg_time;
double delay;
double remaining;
int status;
guard.assertIdenticalMutex ( this->client.mutexRef() );
// prevent recursion nightmares by disabling blocking
// for IO from within a CA callback.
if ( epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
return ECA_EVDISALLOW;
}
if ( timeout < 0.0 ) {
return ECA_TIMEOUT;
}
cur_time = epicsTime::getCurrent ();
this->client.flush ( guard );
beg_time = cur_time;
delay = 0.0;
while ( 1 ) {
if ( this->ioPendingList.count() == 0u ) {
status = ECA_NORMAL;
break;
}
remaining = timeout - delay;
if ( remaining <= CAC_SIGNIFICANT_DELAY ) {
/*
* Make sure that we take care of
* recv backlog at least once
*/
status = ECA_TIMEOUT;
break;
}
if ( pcbGuard ) {
epicsGuardRelease < epicsMutex > unguard ( guard );
{
epicsGuardRelease < epicsMutex > uncbGuard ( *pcbGuard );
this->sem.wait ( remaining );
}
}
else {
epicsGuardRelease < epicsMutex > unguard ( guard );
this->sem.wait ( remaining );
}
/*
* force a time update
*/
cur_time = epicsTime::getCurrent ();
delay = cur_time - beg_time;
}
return status;
}
void CASG::reset (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->destroyCompletedIO ( cbGuard, guard );
this->destroyPendingIO ( cbGuard, guard );
}
// lock must be applied
void CASG::destroyCompletedIO (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
syncGroupNotify * pNotify;
while ( ( pNotify = this->ioCompletedList.get () ) ) {
pNotify->destroy ( cbGuard, guard );
}
}
void CASG::destroyPendingIO (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
while ( syncGroupNotify * pNotify = this->ioPendingList.first () ) {
pNotify->cancel ( cbGuard, guard );
// cancel must release the guard while
// canceling put callbacks so we
// must double check list membership
if ( pNotify->ioPending ( guard ) ) {
this->ioPendingList.remove ( *pNotify );
}
else {
this->ioCompletedList.remove ( *pNotify );
}
pNotify->destroy ( cbGuard, guard );
}
}
void CASG::show ( unsigned level ) const
{
epicsGuard < epicsMutex > guard ( this->client.mutexRef () );
this->show ( guard, level );
}
void CASG::show (
epicsGuard < epicsMutex > & guard, unsigned level ) const
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
::printf ( "Sync Group: id=%u, magic=%u, opPend=%u\n",
this->getId (), this->magic, this->ioPendingList.count () );
if ( level ) {
::printf ( "\tPending" );
tsDLIterConst < syncGroupNotify > notifyPending =
this->ioPendingList.firstIter ();
while ( notifyPending.valid () ) {
notifyPending->show ( guard, level - 1u );
notifyPending++;
}
::printf ( "\tCompleted" );
tsDLIterConst < syncGroupNotify > notifyCompleted =
this->ioCompletedList.firstIter ();
while ( notifyCompleted.valid () ) {
notifyCompleted->show ( guard, level - 1u );
notifyCompleted++;
}
}
}
bool CASG::ioComplete (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->destroyCompletedIO ( cbGuard, guard );
return this->ioPendingList.count () == 0u;
}
void CASG::put ( epicsGuard < epicsMutex > & guard, chid pChan,
unsigned type, arrayElementCount count, const void * pValue )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
sgAutoPtr < syncGroupWriteNotify > pNotify ( guard, *this );
pNotify = syncGroupWriteNotify::factory (
this->freeListWriteOP, *this, & CASG :: recycleWriteNotifyIO, pChan );
pNotify->begin ( guard, type, count, pValue );
pNotify.release ();
}
void CASG::get ( epicsGuard < epicsMutex > & guard, chid pChan,
unsigned type, arrayElementCount count, void *pValue )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
sgAutoPtr < syncGroupReadNotify > pNotify ( guard, *this );
pNotify = syncGroupReadNotify::factory (
this->freeListReadOP, *this, & CASG :: recycleReadNotifyIO, pChan, pValue );
pNotify->begin ( guard, type, count );
pNotify.release ();
}
void CASG::completionNotify (
epicsGuard < epicsMutex > & guard, syncGroupNotify & notify )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->ioPendingList.remove ( notify );
this->ioCompletedList.add ( notify );
if ( this->ioPendingList.count () == 0u ) {
this->sem.signal ();
}
}
void CASG :: recycleReadNotifyIO ( epicsGuard < epicsMutex > & guard,
syncGroupReadNotify & io )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->freeListReadOP.release ( & io );
}
void CASG :: recycleWriteNotifyIO ( epicsGuard < epicsMutex > & guard,
syncGroupWriteNotify & io )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->freeListWriteOP.release ( & io );
}
int CASG :: printFormated ( const char *pformat, ... )
{
va_list theArgs;
int status;
va_start ( theArgs, pformat );
status = this->client.varArgsPrintFormated ( pformat, theArgs );
va_end ( theArgs );
return status;
}
void CASG::exception (
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
const char * pFileName, unsigned lineNo )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
if ( status != ECA_CHANDESTROY ) {
this->client.exception (
guard, status, pContext, pFileName, lineNo );
}
}
void CASG::exception (
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
unsigned type, arrayElementCount count, unsigned op )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
if ( status != ECA_CHANDESTROY ) {
this->client.exception (
guard, status, pContext, pFileName,
lineNo, chan, type, count, op );
}
}
void CASG::operator delete ( void * )
{
// Visual C++ .net appears to require operator delete if
// placement operator delete is defined? I smell a ms rat
// because if I declare placement new and delete, but
// comment out the placement delete definition there are
// no undefined symbols.
errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
__FILE__, __LINE__ );
}

4504
src/ca/client/CAref.html Normal file

File diff suppressed because it is too large Load Diff

118
src/ca/client/Makefile Normal file
View File

@@ -0,0 +1,118 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
TOP=../../..
include $(TOP)/configure/CONFIG
HTMLS += CAref.html
#
# includes to install from this subproject
#
INC += cadef.h
INC += caerr.h
INC += caeventmask.h
INC += caProto.h
INC += db_access.h
INC += addrList.h
INC += cacIO.h
INC += caDiagnostics.h
LIBSRCS += cac.cpp
LIBSRCS += cacChannel.cpp
LIBSRCS += cacChannelNotify.cpp
LIBSRCS += cacContextNotify.cpp
LIBSRCS += cacReadNotify.cpp
LIBSRCS += cacWriteNotify.cpp
LIBSRCS += cacStateNotify.cpp
LIBSRCS += access.cpp
LIBSRCS += iocinf.cpp
LIBSRCS += convert.cpp
LIBSRCS += test_event.cpp
LIBSRCS += repeater.cpp
LIBSRCS += searchTimer.cpp
LIBSRCS += disconnectGovernorTimer.cpp
LIBSRCS += repeaterSubscribeTimer.cpp
LIBSRCS += baseNMIU.cpp
LIBSRCS += nciu.cpp
LIBSRCS += netiiu.cpp
LIBSRCS += udpiiu.cpp
LIBSRCS += tcpiiu.cpp
LIBSRCS += noopiiu.cpp
LIBSRCS += netReadNotifyIO.cpp
LIBSRCS += netWriteNotifyIO.cpp
LIBSRCS += netSubscription.cpp
LIBSRCS += tcpSendWatchdog.cpp
LIBSRCS += tcpRecvWatchdog.cpp
LIBSRCS += bhe.cpp
LIBSRCS += ca_client_context.cpp
LIBSRCS += oldChannelNotify.cpp
LIBSRCS += oldSubscription.cpp
LIBSRCS += getCallback.cpp
LIBSRCS += getCopy.cpp
LIBSRCS += putCallback.cpp
LIBSRCS += syncgrp.cpp
LIBSRCS += CASG.cpp
LIBSRCS += syncGroupNotify.cpp
LIBSRCS += syncGroupReadNotify.cpp
LIBSRCS += syncGroupWriteNotify.cpp
LIBSRCS += localHostName.cpp
LIBSRCS += comQueRecv.cpp
LIBSRCS += comQueSend.cpp
LIBSRCS += comBuf.cpp
LIBSRCS += hostNameCache.cpp
LIBSRCS += msgForMultiplyDefinedPV.cpp
LIBSRCS_vxWorks += templateInstances.cpp
LIBRARY=ca
ca_RCS = ca.rc
ca_LIBS = Com
ca_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
# libs needed for PROD and TESTPRODUCT
PROD_LIBS = ca Com
# needed when its an object library build
PROD_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
PROD_DEFAULT += caRepeater catime acctst caConnTest casw caEventRate
PROD_vxWorks = -nil-
PROD_RTEMS = -nil-
PROD_iOS = -nil-
OBJS_vxWorks = catime acctst caConnTest casw caEventRate acctstRegister
caRepeater_SRCS = caRepeater.cpp
catime_SRCS = catimeMain.c catime.c
acctst_SRCS = acctstMain.c acctst.c
caEventRate_SRCS = caEventRateMain.cpp caEventRate.cpp
casw_SRCS = casw.cpp
caConnTest_SRCS = caConnTestMain.cpp caConnTest.cpp
casw_SYS_LIBS_solaris = socket
SCRIPTS_HOST = S99caRepeater
SCRIPTS_Linux = caRepeater.service
EXPAND += S99caRepeater@
EXPAND += caRepeater.service@
EXPAND_VARS = INSTALL_BIN=$(abspath $(INSTALL_BIN))
SRC_DIRS += $(TOP)/src/ca/client/test
PROD_HOST += ca_test
ca_test_SRCS = ca_test_main.c ca_test.c
ca_test_LIBS = ca Com
ca_test_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
OBJS_vxWorks += ca_test
include $(TOP)/configure/RULES

View File

@@ -0,0 +1,28 @@
#!/bin/sh
#
# System-V init script for the EPICS CA Repeater.
#
INSTALL_BIN=@INSTALL_BIN@
# To change the default values for the EPICS environment parameters,
# uncomment and modify the relevant lines below. These are the only
# EPICS environment variables that the CA Repeater makes use of.
# EPICS_CA_REPEATER_PORT="5065" export EPICS_CA_REPEATER_PORT
if [ $1 = "start" ]; then
if [ -x $INSTALL_BIN/caRepeater ]; then
echo "Starting EPICS CA Repeater "
$INSTALL_BIN/caRepeater &
fi
else
if [ $1 = "stop" ]; then
pid=`ps -e | sed -ne '/caRepeat/s/^ *\([1-9][0-9]*\).*$/\1/p'`
if [ "${pid}" != "" ]; then
echo "Stopping EPICS CA Repeater "
kill ${pid}
fi
fi
fi

View File

@@ -0,0 +1,39 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef SearchDest_h
#define SearchDest_h
#include <osiSock.h>
#include <epicsTime.h>
#include <tsDLList.h>
#include "caProto.h"
class channelNode;
class epicsMutex;
template < class T > class epicsGuard;
struct SearchDest :
public tsDLNode < SearchDest > {
virtual ~SearchDest () {};
struct Callback {
virtual ~Callback () {};
virtual void notify (
const caHdr & msg, const void * pPayload,
const osiSockAddr & addr, const epicsTime & ) = 0;
virtual void show (
epicsGuard < epicsMutex > &, unsigned level ) const = 0;
};
virtual void searchRequest ( epicsGuard < epicsMutex > &,
const char * pbuf, size_t len ) = 0;
virtual void show ( epicsGuard < epicsMutex > &, unsigned level ) const = 0;
};
#endif // SearchDest_h

1107
src/ca/client/access.cpp Normal file

File diff suppressed because it is too large Load Diff

3555
src/ca/client/acctst.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "cadef.h"
#include "caDiagnostics.h"
int main ( int argc, char **argv )
{
unsigned progressLoggingLevel;
unsigned channelCount;
unsigned repetitionCount;
enum ca_preemptive_callback_select preempt;
int aBoolean;
if ( argc < 2 || argc > 6 ) {
printf ("usage: %s <PV name> [progress logging level] [channel count] "
"[repetition count] [enable preemptive callback]\n",
argv[0] );
return 1;
}
if ( argc >= 3 ) {
progressLoggingLevel = atoi ( argv[2] );
}
else {
progressLoggingLevel = 0;
}
if ( argc >= 4 ) {
channelCount = atoi ( argv[3] );
}
else {
channelCount = 20000;
}
if ( argc >= 5 ) {
repetitionCount = atoi ( argv[4] );
}
else {
repetitionCount = 1;
}
if ( argc >= 6 ) {
aBoolean = atoi ( argv[5] );
}
else {
aBoolean = 0;
}
if ( aBoolean ) {
preempt = ca_enable_preemptive_callback;
}
else {
preempt = ca_disable_preemptive_callback;
}
acctst ( argv[1], progressLoggingLevel, channelCount, repetitionCount, preempt );
return 0;
}

View File

@@ -0,0 +1,69 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* CA client library diagnostics IOC shell registration
* Authors:
* Jeff Hill
*/
#include <iocsh.h>
#include "caDiagnostics.h"
/* Information needed by iocsh */
static const iocshArg acctstArg0 = { "channel name", iocshArgString };
static const iocshArg acctstArg1 = { "interest level", iocshArgInt };
static const iocshArg acctstArg2 = { "channel count", iocshArgInt };
static const iocshArg acctstArg3 = { "repetition count", iocshArgInt };
static const iocshArg acctstArg4 = { "preemptive callback select", iocshArgInt };
static const iocshArg *acctstArgs[] =
{
&acctstArg0,
&acctstArg1,
&acctstArg2,
&acctstArg3,
&acctstArg4
};
static const iocshFuncDef acctstFuncDef = {"acctst", 5, acctstArgs};
/* Wrapper called by iocsh, selects the argument types that print needs */
static void acctstCallFunc(const iocshArgBuf *args) {
if ( args[1].ival < 0 ) {
printf ( "negative interest level not allowed\n" );
return;
}
if ( args[2].ival < 0 ) {
printf ( "negative channel count not allowed\n" );
return;
}
if ( args[3].ival < 0 ) {
printf ( "negative repetition count not allowed\n" );
return;
}
acctst (
args[0].sval, /* channel name */
( unsigned ) args[1].ival, /* interest level */
( unsigned ) args[2].ival, /* channel count */
( unsigned ) args[3].ival, /* repetition count */
( ca_preemptive_callback_select ) args[4].ival ); /* preemptive callback select */
}
struct AutoInit {
AutoInit ();
};
AutoInit :: AutoInit ()
{
iocshRegister ( &acctstFuncDef, acctstCallFunc );
}
AutoInit autoInit;

40
src/ca/client/addrList.h Normal file
View File

@@ -0,0 +1,40 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef addrListh
#define addrListh
#include "shareLib.h"
#include "envDefs.h"
#include "osiSock.h"
#ifdef __cplusplus
extern "C" {
#endif
epicsShareFunc void epicsShareAPI configureChannelAccessAddressList
( struct ELLLIST *pList, SOCKET sock, unsigned short port );
epicsShareFunc int epicsShareAPI addAddrToChannelAccessAddressList
( struct ELLLIST *pList, const ENV_PARAM *pEnv,
unsigned short port, int ignoreNonDefaultPort );
epicsShareFunc void epicsShareAPI printChannelAccessAddressList
( const struct ELLLIST *pList );
epicsShareFunc void epicsShareAPI removeDuplicateAddresses
( struct ELLLIST *pDestList, ELLLIST *pSrcList, int silent);
#ifdef __cplusplus
}
#endif
#endif /* ifndef addrListh */

View File

@@ -0,0 +1,94 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifndef autoPtrDestroyh
#define autoPtrDestroyh
template < class T >
class autoPtrDestroy {
public:
autoPtrDestroy ( T * );
~autoPtrDestroy ();
T & operator * () const;
T * operator -> () const;
autoPtrDestroy<T> & operator = ( T * );
T * get () const;
T * release ();
private:
T * p;
// not implemented
autoPtrDestroy<T> & operator = ( const autoPtrDestroy<T> & );
autoPtrDestroy ( const autoPtrDestroy<T> & );
};
template < class T >
inline autoPtrDestroy<T>::autoPtrDestroy ( T *pIn ) :
p ( pIn ) {}
template < class T >
inline autoPtrDestroy<T>::~autoPtrDestroy ()
{
if ( this->p ) {
this->p->destroy ();
}
}
template < class T >
inline T & autoPtrDestroy<T>::operator * () const
{
return * this->p;
}
template < class T >
inline T * autoPtrDestroy<T>::operator -> () const
{
return this->p;
}
template < class T >
inline autoPtrDestroy<T> & autoPtrDestroy<T>::operator = ( T * pIn )
{
if ( this->p ) {
this->p->destroy ();
}
this->p = pIn;
return *this;
}
template < class T >
inline T * autoPtrDestroy<T>::get () const
{
return this->p;
}
template < class T >
inline T * autoPtrDestroy<T>::release ()
{
T *pTmp = this->p;
this->p = 0;
return pTmp;
}
#endif // #ifdef autoPtrDestroyh

View File

@@ -0,0 +1,104 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifndef autoPtrFreeListh
#define autoPtrFreeListh
#ifdef epicsExportSharedSymbols
# define autoPtrFreeListh_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include "tsFreeList.h"
#include "compilerDependencies.h"
#ifdef autoPtrFreeListh_epicsExportSharedSymbols
# define epicsExportSharedSymbols
#endif
template < class T, unsigned N = 0x400, class MUTEX = epicsMutex >
class autoPtrFreeList {
public:
autoPtrFreeList ( tsFreeList < T, N, MUTEX > &, T * );
~autoPtrFreeList ();
T & operator * () const;
T * operator -> () const;
T * get () const;
T * release ();
private:
T * p;
tsFreeList < T, N, MUTEX > & freeList;
// not implemented
autoPtrFreeList & operator = ( const autoPtrFreeList & );
autoPtrFreeList ( const autoPtrFreeList < T, N, MUTEX > & );
};
template < class T, unsigned N, class MUTEX >
inline autoPtrFreeList < T, N, MUTEX >::autoPtrFreeList (
tsFreeList < T, N, MUTEX > & freeListIn, T * pIn ) :
p ( pIn ), freeList ( freeListIn ) {}
template < class T, unsigned N, class MUTEX >
inline autoPtrFreeList < T, N, MUTEX >::~autoPtrFreeList ()
{
if ( this->p ) {
this->p->~T();
// its probably a good idea to require that the class has placement delete
// by calling it during cleanup if the compiler supports it
# if defined ( CXX_PLACEMENT_DELETE )
T::operator delete ( this->p, this->freeList );
# else
this->freeList.release ( this->p );
# endif
}
}
template < class T, unsigned N, class MUTEX >
inline T & autoPtrFreeList < T, N, MUTEX >::operator * () const
{
return * this->p;
}
template < class T, unsigned N, class MUTEX >
inline T * autoPtrFreeList < T, N, MUTEX >::operator -> () const
{
return this->p;
}
template < class T, unsigned N, class MUTEX >
inline T * autoPtrFreeList < T, N, MUTEX >::get () const
{
return this->p;
}
template < class T, unsigned N, class MUTEX >
inline T * autoPtrFreeList < T, N, MUTEX >::release ()
{
T *pTmp = this->p;
this->p = 0;
return pTmp;
}
#endif // #ifdef autoPtrFreeListh

View File

@@ -0,0 +1,92 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifndef autoPtrRecycleh
#define autoPtrRecycleh
template < class T >
class autoPtrRecycle {
public:
autoPtrRecycle (
epicsGuard < epicsMutex > &, chronIntIdResTable < baseNMIU > &,
cacRecycle &, T * );
~autoPtrRecycle ();
T & operator * () const;
T * operator -> () const;
T * get () const;
T * release ();
private:
T * p;
cacRecycle & r;
chronIntIdResTable < baseNMIU > & ioTable;
epicsGuard < epicsMutex > & guard;
// not implemented
autoPtrRecycle ( const autoPtrRecycle & );
autoPtrRecycle & operator = ( const autoPtrRecycle & );
};
template < class T >
inline autoPtrRecycle<T>::autoPtrRecycle (
epicsGuard < epicsMutex > & guardIn, chronIntIdResTable < baseNMIU > & tbl,
cacRecycle & rIn, T * pIn ) :
p ( pIn ), r ( rIn ), ioTable ( tbl ), guard ( guardIn ) {}
template < class T >
inline autoPtrRecycle<T>::~autoPtrRecycle ()
{
if ( this->p ) {
baseNMIU *pb = this->p;
this->ioTable.remove ( *pb );
pb->destroy ( this->guard, this->r );
}
}
template < class T >
inline T & autoPtrRecycle<T>::operator * () const
{
return * this->p;
}
template < class T >
inline T * autoPtrRecycle<T>::operator -> () const
{
return this->p;
}
template < class T >
inline T * autoPtrRecycle<T>::get () const
{
return this->p;
}
template < class T >
inline T * autoPtrRecycle<T>::release ()
{
T *pTmp = this->p;
this->p = 0;
return pTmp;
}
#endif // #ifdef autoPtrRecycleh

View File

@@ -0,0 +1,39 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, the Regents of the University of California.
*
* Author: Jeff Hill
*/
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "iocinf.h"
#include "nciu.h"
#include "netIO.h"
baseNMIU::~baseNMIU ()
{
}
void baseNMIU::forceSubscriptionUpdate (
epicsGuard < epicsMutex > &, nciu & )
{
}

358
src/ca/client/bhe.cpp Normal file
View File

@@ -0,0 +1,358 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#include <string>
#include <stdexcept>
#include <limits.h>
#include <float.h>
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "errlog.h"
#define epicsExportSharedSymbols
#include "iocinf.h"
#include "virtualCircuit.h"
#include "bhe.h"
/*
* 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
*
* if creating this in response to a search reply
* and not in response to a beacon then
* we set the beacon time stamp to
* zero (so we can correctly compute the period
* between the 1st and 2nd beacons)
*/
bhe::bhe ( epicsMutex & mutexIn, const epicsTime & initialTimeStamp,
unsigned initialBeaconNumber, const inetAddrID & addr ) :
inetAddrID ( addr ), timeStamp ( initialTimeStamp ), averagePeriod ( - DBL_MAX ),
mutex ( mutexIn ), pIIU ( 0 ), lastBeaconNumber ( initialBeaconNumber )
{
# ifdef DEBUG
{
char name[64];
addr.name ( name, sizeof ( name ) );
::printf ( "created beacon entry for %s\n", name );
}
# endif
}
bhe::~bhe ()
{
}
void bhe::beaconAnomalyNotify ( epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
if ( this->pIIU ) {
this->pIIU->beaconAnomalyNotify ( guard );
}
}
#ifdef DEBUG
void bhe::logBeacon ( const char * pDiagnostic,
const double & currentPeriod,
const epicsTime & currentTime )
{
if ( this->pIIU ) {
char name[64];
this->name ( name, sizeof ( name ) );
char date[64];
currentTime.strftime ( date, sizeof ( date ),
"%a %b %d %Y %H:%M:%S.%f");
::printf ( "%s cp=%g ap=%g %s %s\n",
pDiagnostic, currentPeriod,
this->averagePeriod, name, date );
}
}
#else
inline void bhe::logBeacon ( const char * /* pDiagnostic */,
const double & /* currentPeriod */,
const epicsTime & /* currentTime */ )
{
}
#endif
#ifdef DEBUG
void bhe::logBeaconDiscard ( unsigned beaconAdvance,
const epicsTime & currentTime )
{
if ( this->pIIU ) {
char name[64];
this->name ( name, sizeof ( name ) );
char date[64];
currentTime.strftime ( date, sizeof ( date ),
"%a %b %d %Y %H:%M:%S.%f");
::printf ( "bb %u %s %s\n",
beaconAdvance, name, date );
}
}
#else
void bhe::logBeaconDiscard ( unsigned /* beaconAdvance */,
const epicsTime & /* currentTime */ )
{
}
#endif
/*
* update beacon period
*
* updates beacon period, and looks for beacon anomalies
*/
bool bhe::updatePeriod (
epicsGuard < epicsMutex > & guard, const epicsTime & programBeginTime,
const epicsTime & currentTime, ca_uint32_t beaconNumber,
unsigned protocolRevision )
{
guard.assertIdenticalMutex ( this->mutex );
//
// this block is enetered if the beacon was created as a side effect of
// creating a connection and so we dont yet know the first beacon time
// and sequence number
//
if ( this->timeStamp == epicsTime () ) {
if ( CA_V410 ( protocolRevision ) ) {
this->lastBeaconNumber = beaconNumber;
}
this->beaconAnomalyNotify ( guard );
/*
* this is the 1st beacon seen - the beacon time stamp
* was not initialized during BHE create because
* a TCP/IP connection created the beacon.
* (nothing to do but set the beacon time stamp and return)
*/
this->timeStamp = currentTime;
logBeacon ( "fb", - DBL_MAX, currentTime );
return false;
}
// 1) detect beacon duplications due to redundant routes
// 2) detect lost beacons due to input queue overrun or damage
if ( CA_V410 ( protocolRevision ) ) {
unsigned beaconSeqAdvance;
if ( beaconNumber >= this->lastBeaconNumber ) {
beaconSeqAdvance = beaconNumber - this->lastBeaconNumber;
}
else {
beaconSeqAdvance = ( ca_uint32_max - this->lastBeaconNumber ) + beaconNumber;
}
this->lastBeaconNumber = beaconNumber;
// throw out sequence numbers just prior to, or the same as, the last one received
// (this situation is probably caused by a temporary duplicate route )
if ( beaconSeqAdvance == 0 || beaconSeqAdvance > ca_uint32_max - 256 ) {
logBeaconDiscard ( beaconSeqAdvance, currentTime );
return false;
}
// throw out sequence numbers that jump forward by only a few numbers
// (this situation is probably caused by a duplicate route
// or a beacon due to input queue overun)
if ( beaconSeqAdvance > 1 && beaconSeqAdvance < 4 ) {
logBeaconDiscard ( beaconSeqAdvance, currentTime );
return false;
}
}
// compute the beacon period (if we have seen at least two beacons)
bool netChange = false;
double currentPeriod = currentTime - this->timeStamp;
if ( this->averagePeriod < 0.0 ) {
double totalRunningTime;
this->beaconAnomalyNotify ( guard );
/*
* this is the 2nd beacon seen. We cant tell about
* the change in period at this point so we just
* initialize the average period and return.
*/
this->averagePeriod = currentPeriod;
logBeacon ( "fp", currentPeriod, currentTime );
/*
* ignore beacons seen for the first time shortly after
* init, but do not ignore beacons arriving with a short
* period because the IOC was rebooted soon after the
* client starts up.
*/
totalRunningTime = this->timeStamp - programBeginTime;
if ( currentPeriod <= totalRunningTime ) {
netChange = true;
}
}
else {
/*
* Is this an IOC seen because of a restored
* network segment?
*
* It may be possible to get false triggers here
* if the client is busy, but this does not cause
* problems because the echo response will tell us
* that the server is available
*/
if ( currentPeriod >= this->averagePeriod * 1.25 ) {
/*
* trigger on any missing beacon
* if connected to this server
*/
this->beaconAnomalyNotify ( guard );
if ( currentPeriod >= this->averagePeriod * 3.25 ) {
/*
* trigger on any 3 contiguous missing beacons
* if not connected to this server
*/
netChange = true;
}
logBeacon ( "bah", currentPeriod, currentTime );
}
/*
* Is this an IOC seen because of an IOC reboot
* (beacon come at a higher rate just after the
* IOC reboots). Lower tolarance here because we
* dont have to worry about lost beacons.
*
* It may be possible to get false triggers here
* if the client is busy, but this does not cause
* problems because the echo response will tell us
* that the server is available
*/
else if ( currentPeriod <= this->averagePeriod * 0.80 ) {
this->beaconAnomalyNotify ( guard );
netChange = true;
logBeacon ( "bal", currentPeriod, currentTime );
}
else if ( this->pIIU ) {
// update state of health for active virtual circuits
// if the beacon looks ok
this->pIIU->beaconArrivalNotify ( guard );
logBeacon ( "vb", currentPeriod, currentTime );
}
// update a running average period
this->averagePeriod = currentPeriod * 0.125 +
this->averagePeriod * 0.875;
}
this->timeStamp = currentTime;
return netChange;
}
void bhe::show ( unsigned level ) const
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->show ( guard, level );
}
void bhe::show ( epicsGuard < epicsMutex > &, unsigned level ) const
{
char host [64];
this->name ( host, sizeof ( host ) );
if ( this->averagePeriod == -DBL_MAX ) {
::printf ( "CA beacon hash entry for %s <no period estimate>\n",
host );
}
else {
::printf ( "CA beacon hash entry for %s with period estimate %f\n",
host, this->averagePeriod );
}
if ( level > 0u ) {
char date[64];
this->timeStamp.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S");
::printf ( "\tbeacon number %u, on %s\n",
this->lastBeaconNumber, date );
}
}
double bhe::period ( epicsGuard < epicsMutex > & guard ) const
{
guard.assertIdenticalMutex ( this->mutex );
return this->averagePeriod;
}
epicsTime bhe::updateTime ( epicsGuard < epicsMutex > & guard ) const
{
guard.assertIdenticalMutex ( this->mutex );
return this->timeStamp;
}
void bhe::registerIIU (
epicsGuard < epicsMutex > & guard, tcpiiu & iiu )
{
guard.assertIdenticalMutex ( this->mutex );
this->pIIU = & iiu;
}
void bhe::unregisterIIU (
epicsGuard < epicsMutex > & guard, tcpiiu & iiu )
{
guard.assertIdenticalMutex ( this->mutex );
if ( this->pIIU == & iiu ) {
this->pIIU = 0;
this->timeStamp = epicsTime();
this->averagePeriod = - DBL_MAX;
logBeacon ( "ui", this->averagePeriod, epicsTime::getCurrent () );
}
}
void bhe::operator delete ( void * )
{
// Visual C++ .net appears to require operator delete if
// placement operator delete is defined? I smell a ms rat
// because if I declare placement new and delete, but
// comment out the placement delete definition there are
// no undefined symbols.
errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
__FILE__, __LINE__ );
}
void * bheFreeStore::allocate ( size_t size )
{
return freeList.allocate ( size );
}
void bheFreeStore::release ( void * pCadaver )
{
freeList.release ( pCadaver );
}
bheMemoryManager::~bheMemoryManager () {}

122
src/ca/client/bhe.h Normal file
View File

@@ -0,0 +1,122 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#ifndef bheh
#define bheh
#ifdef epicsExportSharedSymbols
# define bhehEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include "tsDLList.h"
#include "tsFreeList.h"
#include "epicsTime.h"
#include "compilerDependencies.h"
#ifdef bhehEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# include "shareLib.h"
#endif
#include "inetAddrID.h"
#include "caProto.h"
class tcpiiu;
class bheMemoryManager;
// using a pure abstract wrapper class around the free list avoids
// Tornado 2.0.1 GNU compiler bugs
class epicsShareClass bheMemoryManager {
public:
virtual ~bheMemoryManager ();
virtual void * allocate ( size_t ) = 0;
virtual void release ( void * ) = 0;
};
class bhe : public tsSLNode < bhe >, public inetAddrID {
public:
epicsShareFunc bhe (
epicsMutex &, const epicsTime & initialTimeStamp,
unsigned initialBeaconNumber, const inetAddrID & addr );
epicsShareFunc ~bhe ();
epicsShareFunc bool updatePeriod (
epicsGuard < epicsMutex > &,
const epicsTime & programBeginTime,
const epicsTime & currentTime, ca_uint32_t beaconNumber,
unsigned protocolRevision );
epicsShareFunc double period ( epicsGuard < epicsMutex > & ) const;
epicsShareFunc epicsTime updateTime ( epicsGuard < epicsMutex > & ) const;
epicsShareFunc void show ( unsigned level ) const;
epicsShareFunc void show ( epicsGuard < epicsMutex > &, unsigned /* level */ ) const;
epicsShareFunc void registerIIU ( epicsGuard < epicsMutex > &, tcpiiu & );
epicsShareFunc void unregisterIIU ( epicsGuard < epicsMutex > &, tcpiiu & );
epicsShareFunc void * operator new ( size_t size, bheMemoryManager & );
#ifdef CXX_PLACEMENT_DELETE
epicsShareFunc void operator delete ( void *, bheMemoryManager & );
#endif
private:
epicsTime timeStamp;
double averagePeriod;
epicsMutex & mutex;
tcpiiu * pIIU;
ca_uint32_t lastBeaconNumber;
void beaconAnomalyNotify ( epicsGuard < epicsMutex > & );
void logBeacon ( const char * pDiagnostic,
const double & currentPeriod,
const epicsTime & currentTime );
void logBeaconDiscard ( unsigned beaconAdvance,
const epicsTime & currentTime );
bhe ( const bhe & );
bhe & operator = ( const bhe & );
epicsShareFunc void operator delete ( void * );
};
// using a wrapper class around the free list avoids
// Tornado 2.0.1 GNU compiler bugs
class bheFreeStore : public bheMemoryManager {
public:
bheFreeStore () {}
void * allocate ( size_t );
void release ( void * );
private:
tsFreeList < bhe, 0x100 > freeList;
bheFreeStore ( const bheFreeStore & );
bheFreeStore & operator = ( const bheFreeStore & );
};
inline void * bhe::operator new ( size_t size,
bheMemoryManager & mgr )
{
return mgr.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void bhe::operator delete ( void * pCadaver,
bheMemoryManager & mgr )
{
mgr.release ( pCadaver );
}
#endif
#endif // ifdef bheh

36
src/ca/client/ca.rc Normal file
View File

@@ -0,0 +1,36 @@
#include <winver.h>
#include "epicsVersion.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION EPICS_VERSION,EPICS_REVISION,EPICS_MODIFICATION,EPICS_PATCH_LEVEL
PRODUCTVERSION EPICS_VERSION,EPICS_REVISION,EPICS_MODIFICATION,EPICS_PATCH_LEVEL
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_UNKNOWN
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments","Channel Access Library for EPICS\0"
VALUE "CompanyName", "The EPICS collaboration\0"
VALUE "FileDescription", "Channel Access Library\0"
VALUE "FileVersion", EPICS_VERSION_STRING "\0"
VALUE "InternalName", "ca\0"
VALUE "LegalCopyright", "Copyright (C) Univ. of California, Univ. of Chicago\0"
VALUE "OriginalFilename", "ca.dll\0"
VALUE "ProductName", "Experimental Physics and Industrial Control System (EPICS)\0"
VALUE "ProductVersion", EPICS_VERSION_STRING "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -0,0 +1,109 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "cadef.h"
#include "epicsTime.h"
static unsigned channelCount = 0u;
static unsigned connCount = 0u;
static bool subsequentConnect = false;
epicsTime begin;
extern "C" void caConnTestConnHandler ( struct connection_handler_args args )
{
if ( args.op == CA_OP_CONN_UP ) {
if ( connCount == 0u ) {
if ( subsequentConnect ) {
printf ("the first channel connected\n");
begin = epicsTime::getCurrent ();
}
}
connCount++;
// printf ( "." );
// fflush ( stdout );
if ( connCount == channelCount ) {
epicsTime current = epicsTime::getCurrent ();
double delay = current - begin;
printf ( "all channels connected after %f sec ( %f sec per channel)\n",
delay, delay / channelCount );
}
}
else if ( args.op == CA_OP_CONN_DOWN ) {
if ( connCount == channelCount ) {
printf ( "channels are disconnected\n" );
subsequentConnect = true;
}
connCount--;
if ( connCount == 0u ) {
printf ( "all channels are disconnected\n" );
}
}
else {
assert ( 0 );
}
}
void caConnTest ( const char *pNameIn, unsigned channelCountIn, double delayIn )
{
unsigned iteration = 0u;
int status;
unsigned i;
chid *pChans;
channelCount = channelCountIn;
pChans = new chid [channelCount];
while ( 1 ) {
connCount = 0u;
subsequentConnect = false;
begin = epicsTime::getCurrent ();
printf ( "initializing CA client library\n" );
status = ca_task_initialize();
SEVCHK ( status, "CA init failed" );
printf ( "creating channels\n" );
for ( i = 0u; i < channelCount; i++ ) {
status = ca_search_and_connect ( pNameIn,
&pChans[i], caConnTestConnHandler, 0 );
SEVCHK ( status, "CA search problems" );
}
printf ( "all channels were created\n" );
ca_pend_event ( delayIn );
if ( iteration & 1 ) {
for ( i = 0u; i < channelCount; i++ ) {
status = ca_clear_channel ( pChans[i] );
SEVCHK ( status, "ca_clear_channel() problems" );
}
printf ( "all channels were destroyed\n" );
}
printf ( "shutting down CA client library\n" );
status = ca_task_exit ();
SEVCHK ( status, "task exit problems" );
iteration++;
}
//delete [] pChans;
}

View File

@@ -0,0 +1,45 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdio.h>
#include <epicsStdlib.h>
#include "caDiagnostics.h"
int main ( int argc, char **argv )
{
double delay = 60.0 * 5.0;
unsigned count = 2000;
if ( argc < 2 || argc > 4 ) {
printf ( "usage: %s < channel name > [ < count > ] [ < delay sec > ]\n", argv[0] );
return -1;
}
if ( argc >= 3 ) {
int nConverted = sscanf ( argv[2], "%u", &count );
if ( nConverted != 1 ) {
printf ( "conversion failed, changing channel count arg \"%s\" to %u\n",
argv[1], count );
}
}
if ( argc >= 4 ) {
int nConverted = epicsScanDouble( argv[3], &delay );
if ( nConverted != 1 ) {
printf ( "conversion failed, changing delay arg \"%s\" to %f\n",
argv[2], delay );
}
}
caConnTest ( argv[1], count, delay );
return 0;
}

View File

@@ -0,0 +1,38 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef caDiagnosticsh
#define caDiagnosticsh
#include "cadef.h"
#ifdef __cplusplus
extern "C" {
#endif
enum appendNumberFlag {appendNumber, dontAppendNumber};
int catime ( const char *channelName, unsigned channelCount, enum appendNumberFlag appNF );
int acctst ( const char *pname, unsigned logggingInterestLevel,
unsigned channelCount, unsigned repetitionCount,
enum ca_preemptive_callback_select select );
#define CATIME_OK 0
#define CATIME_ERROR -1
#ifdef __cplusplus
}
#endif
void caConnTest ( const char *pNameIn, unsigned channelCountIn, double delayIn );
#endif /* caDiagnosticsh */

View File

@@ -0,0 +1,139 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdio.h>
#include <limits.h>
#include <math.h>
#include "cadef.h"
#include "dbDefs.h"
#include "epicsTime.h"
#include "errlog.h"
/*
* event_handler()
*/
extern "C" void eventCallBack ( struct event_handler_args args )
{
unsigned *pCount = static_cast < unsigned * > ( args.usr );
(*pCount)++;
}
/*
* caEventRate ()
*/
void caEventRate ( const char *pName, unsigned count )
{
static const double initialSamplePeriod = 1.0;
static const double maxSamplePeriod = 60.0 * 5.0;
unsigned eventCount = 0u;
chid * pChidTable = new chid [ count ];
{
printf ( "Connecting to CA Channel \"%s\" %u times.",
pName, count );
fflush ( stdout );
epicsTime begin = epicsTime::getCurrent ();
for ( unsigned i = 0u; i < count; i++ ) {
int status = ca_search ( pName, & pChidTable[i] );
SEVCHK ( status, NULL );
}
int status = ca_pend_io ( 10000.0 );
if ( status != ECA_NORMAL ) {
fprintf ( stderr, " not found.\n" );
return;
}
epicsTime end = epicsTime::getCurrent ();
printf ( " done(%f sec).\n", end - begin );
}
{
printf ( "Subscribing %u times.", count );
fflush ( stdout );
epicsTime begin = epicsTime::getCurrent ();
for ( unsigned i = 0u; i < count; i++ ) {
int addEventStatus = ca_add_event ( DBR_FLOAT,
pChidTable[i], eventCallBack, &eventCount, NULL);
SEVCHK ( addEventStatus, __FILE__ );
}
int status = ca_flush_io ();
SEVCHK ( status, __FILE__ );
epicsTime end = epicsTime::getCurrent ();
printf ( " done(%f sec).\n", end - begin );
}
{
printf ( "Waiting for initial value events." );
fflush ( stdout );
// let the first one go by
epicsTime begin = epicsTime::getCurrent ();
while ( eventCount < count ) {
int status = ca_pend_event ( 0.01 );
if ( status != ECA_TIMEOUT ) {
SEVCHK ( status, NULL );
}
}
epicsTime end = epicsTime::getCurrent ();
printf ( " done(%f sec).\n", end - begin );
}
double samplePeriod = initialSamplePeriod;
double X = 0.0;
double XX = 0.0;
unsigned N = 0u;
while ( true ) {
unsigned nEvents, lastEventCount, curEventCount;
epicsTime beginPend = epicsTime::getCurrent ();
lastEventCount = eventCount;
int status = ca_pend_event ( samplePeriod );
curEventCount = eventCount;
epicsTime endPend = epicsTime::getCurrent ();
if ( status != ECA_TIMEOUT ) {
SEVCHK ( status, NULL );
}
if ( curEventCount >= lastEventCount ) {
nEvents = curEventCount - lastEventCount;
}
else {
nEvents = ( UINT_MAX - lastEventCount ) + curEventCount + 1u;
}
N++;
double period = endPend - beginPend;
double Hz = nEvents / period;
X += Hz;
XX += Hz * Hz;
double mean = X / N;
double stdDev = sqrt ( XX / N - mean * mean );
printf ( "CA Event Rate (Hz): current %g mean %g std dev %g\n",
Hz, mean, stdDev );
if ( samplePeriod < maxSamplePeriod ) {
samplePeriod += samplePeriod;
}
}
}

View File

@@ -0,0 +1,38 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
void caEventRate ( const char *pName, unsigned count );
int main ( int argc, char **argv )
{
if ( argc < 2 || argc > 3 ) {
fprintf ( stderr, "usage: %s < PV name > [subscription count]\n", argv[0] );
return 0;
}
unsigned count;
if ( argc == 3 ) {
int status = sscanf ( argv[2], " %u ", & count );
if ( status != 1 ) {
fprintf ( stderr, "expected unsigned integer 2nd argument\n" );
return 0;
}
}
else {
count = 1;
}
caEventRate ( argv[1], count );
return 0;
}

215
src/ca/client/caProto.h Normal file
View File

@@ -0,0 +1,215 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifndef __CAPROTO__
#define __CAPROTO__
#define capStrOf(A) #A
#define capStrOfX(A) capStrOf ( A )
/*
* CA protocol revision
* TCP/UDP port number (bumped each major protocol change)
*/
#define CA_MAJOR_PROTOCOL_REVISION 4
#define CA_VERSION_STRING( MINOR_REVISION ) \
( capStrOfX ( CA_MAJOR_PROTOCOL_REVISION ) "." capStrOfX ( MINOR_REVISION ) )
#define CA_UKN_MINOR_VERSION 0u /* unknown minor version */
#if CA_MAJOR_PROTOCOL_REVISION == 4u
# define CA_V41(MINOR) ((MINOR)>=1u)
# define CA_V42(MINOR) ((MINOR)>=2u)
# define CA_V43(MINOR) ((MINOR)>=3u)
# define CA_V44(MINOR) ((MINOR)>=4u)
# define CA_V45(MINOR) ((MINOR)>=5u)
# define CA_V46(MINOR) ((MINOR)>=6u)
# define CA_V47(MINOR) ((MINOR)>=7u)
# define CA_V48(MINOR) ((MINOR)>=8u)
# define CA_V49(MINOR) ((MINOR)>=9u) /* large arrays, dispatch priorities */
# define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */
# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
# define CA_V413(MINOR) ((MINOR)>=13u) /* Allow zero length in requests. */
#elif CA_MAJOR_PROTOCOL_REVISION > 4u
# define CA_V41(MINOR) ( 1u )
# define CA_V42(MINOR) ( 1u )
# define CA_V43(MINOR) ( 1u )
# define CA_V44(MINOR) ( 1u )
# define CA_V45(MINOR) ( 1u )
# define CA_V46(MINOR) ( 1u )
# define CA_V47(MINOR) ( 1u )
# define CA_V48(MINOR) ( 1u )
# define CA_V49(MINOR) ( 1u )
# define CA_V410(MINOR) ( 1u )
# define CA_V411(MINOR) ( 1u )
# define CA_V412(MINOR) ( 1u )
# define CA_V413(MINOR) ( 1u )
#else
# define CA_V41(MINOR) ( 0u )
# define CA_V42(MINOR) ( 0u )
# define CA_V43(MINOR) ( 0u )
# define CA_V44(MINOR) ( 0u )
# define CA_V45(MINOR) ( 0u )
# define CA_V46(MINOR) ( 0u )
# define CA_V47(MINOR) ( 0u )
# define CA_V48(MINOR) ( 0u )
# define CA_V49(MINOR) ( 0u )
# define CA_V410(MINOR) ( 0u )
# define CA_V411(MINOR) ( 0u )
# define CA_V412(MINOR) ( 0u )
# define CA_V413(MINOR) ( 0u )
#endif
/*
* These port numbers are only used if the CA repeater and
* CA server port numbers cant be obtained from the EPICS
* environment variables "EPICS_CA_REPEATER_PORT" and
* "EPICS_CA_SERVER_PORT"
*/
#define CA_PORT_BASE IPPORT_USERRESERVED + 56U
#define CA_SERVER_PORT (CA_PORT_BASE+CA_MAJOR_PROTOCOL_REVISION*2u)
#define CA_REPEATER_PORT (CA_PORT_BASE+CA_MAJOR_PROTOCOL_REVISION*2u+1u)
/*
* 1500 (max of ethernet and 802.{2,3} MTU) - 20(IP) - 8(UDP)
* (the MTU of Ethernet is currently independent of its speed varient)
*/
#define ETHERNET_MAX_UDP ( 1500u - 20u - 8u )
#define MAX_UDP_RECV ( 0xffff + 16u ) /* allow large frames to be received in the future */
#define MAX_UDP_SEND 1024u /* original MAX_UDP */
#define MAX_TCP ( 1024 * 16u ) /* so waveforms fit */
#define MAX_MSG_SIZE ( MAX_TCP ) /* the larger of tcp and udp max */
#define CA_PROTO_PRIORITY_MIN 0u
#define CA_PROTO_PRIORITY_MAX 99u
/*
* architecture independent types
*
* (so far this works on all archs we have ported to)
*/
typedef unsigned char ca_uint8_t;
typedef unsigned short ca_uint16_t;
typedef unsigned int ca_uint32_t;
typedef float ca_float32_t;
typedef ca_uint32_t caResId;
#define ca_uint32_max 0xffffffff
/* values for m_cmmd */
#define CA_PROTO_VERSION 0u /* set minor version and priority (used to be NOOP cmd) */
#define CA_PROTO_EVENT_ADD 1u /* add an event */
#define CA_PROTO_EVENT_CANCEL 2u /* cancel an event */
#define CA_PROTO_READ 3u /* read and return a channel value*/
#define CA_PROTO_WRITE 4u /* write a channel value */
#define CA_PROTO_SNAPSHOT 5u /* snapshot of the system */
#define CA_PROTO_SEARCH 6u /* IOC channel search */
#define CA_PROTO_BUILD 7u /* build - obsolete */
#define CA_PROTO_EVENTS_OFF 8u /* flow control */
#define CA_PROTO_EVENTS_ON 9u /* flow control */
#define CA_PROTO_READ_SYNC 10u /* purge old reads */
#define CA_PROTO_ERROR 11u /* an operation failed */
#define CA_PROTO_CLEAR_CHANNEL 12u /* free chan resources */
#define CA_PROTO_RSRV_IS_UP 13u /* CA server has joined the net */
#define CA_PROTO_NOT_FOUND 14u /* channel not found */
#define CA_PROTO_READ_NOTIFY 15u /* add a one shot event */
#define CA_PROTO_READ_BUILD 16u /* read and build - obsolete */
#define REPEATER_CONFIRM 17u /* registration confirmation */
#define CA_PROTO_CREATE_CHAN 18u /* client creates channel in server */
#define CA_PROTO_WRITE_NOTIFY 19u /* notify after write chan value */
#define CA_PROTO_CLIENT_NAME 20u /* CA V4.1 identify client */
#define CA_PROTO_HOST_NAME 21u /* CA V4.1 identify client */
#define CA_PROTO_ACCESS_RIGHTS 22u /* CA V4.2 asynch access rights chg */
#define CA_PROTO_ECHO 23u /* CA V4.3 connection verify */
#define REPEATER_REGISTER 24u /* register for repeater fan out */
#define CA_PROTO_SIGNAL 25u /* knock the server out of select */
#define CA_PROTO_CREATE_CH_FAIL 26u /* unable to create chan resource in server */
#define CA_PROTO_SERVER_DISCONN 27u /* server deletes PV (or channel) */
#define CA_PROTO_LAST_CMMD CA_PROTO_SERVER_DISCONN
/*
* for use with search and not_found (if search fails and
* its not a broadcast tell the client to look elesewhere)
*/
#define DOREPLY 10u
#define DONTREPLY 5u
/*
* for use with the m_dataType field in UDP messages emitted by servers
*/
#define sequenceNoIsValid 1
/* size of object in bytes rounded up to nearest oct word */
#define OCT_ROUND(A) (((A)+7)/8)
#define OCT_SIZEOF(A) (OCT_ROUND(sizeof(A)))
/* size of object in bytes rounded up to nearest long word */
#define QUAD_ROUND(A) ((A)+3)/4)
#define QUAD_SIZEOF(A) (QUAD_ROUND(sizeof(A)))
/* size of object in bytes rounded up to nearest short word */
#define BI_ROUND(A) (((A)+1)/2)
#define BI_SIZEOF(A) (BI_ROUND(sizeof(A)))
/*
* For communicating access rights to the clients
*
* (placed in m_available hdr field of CA_PROTO_ACCESS_RIGHTS cmmd
*/
#define CA_PROTO_ACCESS_RIGHT_READ (1u<<0u)
#define CA_PROTO_ACCESS_RIGHT_WRITE (1u<<1u)
/*
* All structures passed in the protocol must have individual
* fields aligned on natural boundaries.
*
* NOTE: all structures declared in this file must have a
* byte count which is evenly divisible by 8 matching
* the largest atomic data type in db_access.h.
*/
#define CA_MESSAGE_ALIGN(A) (OCT_ROUND(A)<<3u)
/*
* the common part of each message sent/recv by the
* CA server.
*/
typedef struct ca_hdr {
ca_uint16_t m_cmmd; /* operation to be performed */
ca_uint16_t m_postsize; /* size of payload */
ca_uint16_t m_dataType; /* operation data type */
ca_uint16_t m_count; /* operation data count */
ca_uint32_t m_cid; /* channel identifier */
ca_uint32_t m_available; /* protocol stub dependent */
} caHdr;
/*
* for monitor (event) message extension
*/
struct mon_info {
ca_float32_t m_lval; /* low delta */
ca_float32_t m_hval; /* high delta */
ca_float32_t m_toval; /* period btween samples */
ca_uint16_t m_mask; /* event select mask */
ca_uint16_t m_pad; /* extend to 32 bits */
};
/*
* PV names greater than this length assumed to be invalid
*/
#define unreasonablePVNameSize 500u
#endif /* __CAPROTO__ */

View File

@@ -0,0 +1,42 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* CA UDP repeater standalone executable
*
* Author: Jeff Hill
* Date: 3-27-90
*
* PURPOSE:
* Broadcasts fan out over the LAN, but old IP kernels do not allow
* two processes on the same machine to get the same broadcast
* (and modern IP kernels do not allow two processes on the same machine
* to receive the same unicast).
*
* This code fans out UDP messages sent to the CA repeater port
* to all CA client processes that have subscribed.
*
* NOTES:
*
* see repeater.c
*
*/
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "epicsAssert.h"
#include "udpiiu.h"
int main()
{
ca_repeater ();
return ( 0 );
}

View File

@@ -0,0 +1,25 @@
#
# Linux systemd service file for the EPICS CA Repeater
#
# To install this file, as root:
# cp caRepeater.service /etc/systemd/system
# chmod 664 /etc/systemd/system/caRepeater.service
# systemctl daemon-reload
# systemctl enable caRepeater
# systemctl start caRepeater
#
# To check the status:
# systemctl status caRepeater
[Unit]
Description=EPICS CA Repeater
Requires=network.target
After=network.target
[Service]
ExecStart=@INSTALL_BIN@/caRepeater
Restart=always
User=daemon
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,88 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#ifndef caServerIDh
#define caServerIDh
#include "osiSock.h"
#include "resourceLib.h"
#include "caProto.h"
class caServerID {
public:
caServerID ( const struct sockaddr_in & addrIn, unsigned priority );
bool operator == ( const caServerID & ) const;
resTableIndex hash () const;
osiSockAddr address () const;
unsigned priority () const;
private:
struct sockaddr_in addr;
ca_uint8_t pri;
};
inline caServerID::caServerID (
const struct sockaddr_in & addrIn, unsigned priorityIn ) :
addr ( addrIn ), pri ( static_cast <ca_uint8_t> ( priorityIn ) )
{
assert ( priorityIn <= 0xff );
}
inline bool caServerID::operator == ( const caServerID & rhs ) const
{
if ( this->addr.sin_addr.s_addr == rhs.addr.sin_addr.s_addr &&
this->addr.sin_port == rhs.addr.sin_port &&
this->pri == rhs.pri ) {
return true;
}
return false;
}
inline resTableIndex caServerID::hash () const
{
// start with a very small server table to speed
// up the flush traverse for the frequent case -
// a small numbers of servers
const unsigned caServerMinIndexBitWidth = 2u;
const unsigned caServerMaxIndexBitWidth = 32u;
unsigned index;
index = this->addr.sin_addr.s_addr;
index ^= this->addr.sin_port;
index ^= this->addr.sin_port >> 8u;
index ^= this->pri;
return integerHash ( caServerMinIndexBitWidth,
caServerMaxIndexBitWidth, index );
}
inline osiSockAddr caServerID::address () const
{
osiSockAddr tmp;
tmp.ia = this->addr;
return tmp;
}
inline unsigned caServerID::priority () const
{
return this->pri;
}
#endif // ifdef caServerID

View File

@@ -0,0 +1,811 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifdef _MSC_VER
# pragma warning(disable:4355)
#endif
#include <stdexcept>
#include <string> // vxWorks 6.0 requires this include
#include <stdio.h>
#include "epicsExit.h"
#include "errlog.h"
#include "locationException.h"
#define epicsExportSharedSymbols
#include "iocinf.h"
#include "oldAccess.h"
#include "cac.h"
epicsShareDef epicsThreadPrivateId caClientCallbackThreadId;
static epicsThreadOnceId cacOnce = EPICS_THREAD_ONCE_INIT;
const unsigned ca_client_context :: flushBlockThreshold = 0x58000;
extern "C" void cacExitHandler ( void *)
{
epicsThreadPrivateDelete ( caClientCallbackThreadId );
caClientCallbackThreadId = 0;
delete ca_client_context::pDefaultServiceInstallMutex;
}
// runs once only for each process
extern "C" void cacOnceFunc ( void * )
{
caClientCallbackThreadId = epicsThreadPrivateCreate ();
assert ( caClientCallbackThreadId );
ca_client_context::pDefaultServiceInstallMutex = newEpicsMutex;
epicsAtExit ( cacExitHandler,0 );
}
extern epicsThreadPrivateId caClientContextId;
cacService * ca_client_context::pDefaultService = 0;
epicsMutex * ca_client_context::pDefaultServiceInstallMutex;
ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
createdByThread ( epicsThreadGetIdSelf () ),
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ),
pndRecvCnt ( 0u ), ioSeqNo ( 0u ), callbackThreadsPending ( 0u ),
localPort ( 0 ), fdRegFuncNeedsToBeCalled ( false ),
noWakeupSincePend ( true )
{
static const unsigned short PORT_ANY = 0u;
if ( ! osiSockAttach () ) {
throwWithLocation ( noSocket () );
}
epicsThreadOnce ( & cacOnce, cacOnceFunc, 0 );
{
epicsGuard < epicsMutex > guard ( *ca_client_context::pDefaultServiceInstallMutex );
if ( ca_client_context::pDefaultService ) {
this->pServiceContext.reset (
& ca_client_context::pDefaultService->contextCreate (
this->mutex, this->cbMutex, *this ) );
}
else {
this->pServiceContext.reset ( new cac ( this->mutex, this->cbMutex, *this ) );
}
}
this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( this->sock == INVALID_SOCKET ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
this->printFormated (
"ca_client_context: unable to create "
"datagram socket because = \"%s\"\n",
sockErrBuf );
throwWithLocation ( noSocket () );
}
{
osiSockIoctl_t yes = true;
int status = socket_ioctl ( this->sock,
FIONBIO, & yes);
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
epicsSocketDestroy ( this->sock );
this->printFormated (
"%s: non blocking IO set fail because \"%s\"\n",
__FILE__, sockErrBuf );
throwWithLocation ( noSocket () );
}
}
// force a bind to an unconstrained address so we can obtain
// the local port number below
{
osiSockAddr addr;
memset ( (char *)&addr, 0 , sizeof ( addr ) );
addr.ia.sin_family = AF_INET;
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
addr.ia.sin_port = htons ( PORT_ANY );
int status = bind (this->sock, &addr.sa, sizeof (addr) );
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
epicsSocketDestroy (this->sock);
this->printFormated (
"CAC: unable to bind to an unconstrained "
"address because = \"%s\"\n",
sockErrBuf );
throwWithLocation ( noSocket () );
}
}
{
osiSockAddr tmpAddr;
osiSocklen_t saddr_length = sizeof ( tmpAddr );
int status = getsockname ( this->sock, & tmpAddr.sa, & saddr_length );
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
epicsSocketDestroy ( this->sock );
this->printFormated ( "CAC: getsockname () error was \"%s\"\n", sockErrBuf );
throwWithLocation ( noSocket () );
}
if ( tmpAddr.sa.sa_family != AF_INET) {
epicsSocketDestroy ( this->sock );
this->printFormated ( "CAC: UDP socket was not inet addr family\n" );
throwWithLocation ( noSocket () );
}
this->localPort = htons ( tmpAddr.ia.sin_port );
}
epics_auto_ptr < CallbackGuard > pCBGuard;
if ( ! enablePreemptiveCallback ) {
pCBGuard.reset ( new CallbackGuard ( this->cbMutex ) );
}
// multiple steps ensure exception safety
this->pCallbackGuard = pCBGuard;
}
ca_client_context::~ca_client_context ()
{
if ( this->fdRegFunc ) {
( *this->fdRegFunc )
( this->fdRegArg, this->sock, false );
}
epicsSocketDestroy ( this->sock );
osiSockRelease ();
// force a logical shutdown order
// so that the cac class does not hang its
// receive threads during their shutdown sequence
// and so that classes using this classes mutex
// are destroyed before the mutex is destroyed
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < epicsMutex > unguard ( *this->pCallbackGuard );
this->pServiceContext.reset ( 0 );
}
else {
this->pServiceContext.reset ( 0 );
}
}
void ca_client_context::destroyGetCopy (
epicsGuard < epicsMutex > & guard, getCopy & gc )
{
guard.assertIdenticalMutex ( this->mutex );
gc.~getCopy ();
this->getCopyFreeList.release ( & gc );
}
void ca_client_context::destroyGetCallback (
epicsGuard < epicsMutex > & guard, getCallback & gcb )
{
guard.assertIdenticalMutex ( this->mutex );
gcb.~getCallback ();
this->getCallbackFreeList.release ( & gcb );
}
void ca_client_context::destroyPutCallback (
epicsGuard < epicsMutex > & guard, putCallback & pcb )
{
guard.assertIdenticalMutex ( this->mutex );
pcb.~putCallback ();
this->putCallbackFreeList.release ( & pcb );
}
void ca_client_context::destroySubscription (
epicsGuard < epicsMutex > & guard, oldSubscription & os )
{
guard.assertIdenticalMutex ( this->mutex );
os.~oldSubscription ();
this->subscriptionFreeList.release ( & os );
}
void ca_client_context::changeExceptionEvent (
caExceptionHandler * pfunc, void * arg )
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->ca_exception_func = pfunc;
this->ca_exception_arg = arg;
// should block here until releated callback in progress completes
}
void ca_client_context::replaceErrLogHandler (
caPrintfFunc * ca_printf_func )
{
epicsGuard < epicsMutex > guard ( this->mutex );
if ( ca_printf_func ) {
this->pVPrintfFunc = ca_printf_func;
}
else {
this->pVPrintfFunc = epicsVprintf;
}
// should block here until releated callback in progress completes
}
void ca_client_context::registerForFileDescriptorCallBack (
CAFDHANDLER *pFunc, void *pArg )
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->fdRegFunc = pFunc;
this->fdRegArg = pArg;
this->fdRegFuncNeedsToBeCalled = true;
if ( pFunc ) {
// the receive thread might already be blocking
// w/o having sent the wakeup message
this->_sendWakeupMsg ();
}
// should block here until releated callback in progress completes
}
int ca_client_context :: printFormated (
const char *pformat, ... ) const
{
va_list theArgs;
int status;
va_start ( theArgs, pformat );
status = this->ca_client_context :: varArgsPrintFormated ( pformat, theArgs );
va_end ( theArgs );
return status;
}
int ca_client_context :: varArgsPrintFormated (
const char *pformat, va_list args ) const
{
caPrintfFunc * pFunc;
{
epicsGuard < epicsMutex > guard ( this->mutex );
pFunc = this->pVPrintfFunc;
}
if ( pFunc ) {
return ( *pFunc ) ( pformat, args );
}
else {
return :: vfprintf ( stderr, pformat, args );
}
}
void ca_client_context::exception (
epicsGuard < epicsMutex > & guard, int stat, const char * pCtx,
const char * pFile, unsigned lineNo )
{
struct exception_handler_args args;
caExceptionHandler * pFunc = this->ca_exception_func;
void * pArg = this->ca_exception_arg;
{
epicsGuardRelease < epicsMutex > unguard ( guard );
// NOOP if they disable exceptions
if ( pFunc ) {
args.chid = NULL;
args.type = TYPENOTCONN;
args.count = 0;
args.addr = NULL;
args.stat = stat;
args.op = CA_OP_OTHER;
args.ctx = pCtx;
args.pFile = pFile;
args.lineNo = lineNo;
args.usr = pArg;
( *pFunc ) ( args );
}
else {
this->signal ( stat, pFile, lineNo, pCtx );
}
}
}
void ca_client_context::exception (
epicsGuard < epicsMutex > & guard, int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
unsigned type, arrayElementCount count, unsigned op )
{
struct exception_handler_args args;
caExceptionHandler * pFunc = this->ca_exception_func;
void * pArg = this->ca_exception_arg;
{
epicsGuardRelease < epicsMutex > unguard ( guard );
// NOOP if they disable exceptions
if ( pFunc ) {
args.chid = &chan;
args.type = type;
args.count = count;
args.addr = NULL;
args.stat = status;
args.op = op;
args.ctx = pContext;
args.pFile = pFileName;
args.lineNo = lineNo;
args.usr = pArg;
( *pFunc ) ( args );
}
else {
this->signal ( status, pFileName, lineNo,
"op=%u, channel=%s, type=%s, count=%lu, ctx=\"%s\"",
op, ca_name ( &chan ),
dbr_type_to_text ( static_cast <int> ( type ) ),
count, pContext );
}
}
}
void ca_client_context::signal ( int ca_status, const char * pfilenm,
int lineno, const char * pFormat, ... )
{
va_list theArgs;
va_start ( theArgs, pFormat );
this->vSignal ( ca_status, pfilenm, lineno, pFormat, theArgs);
va_end ( theArgs );
}
void ca_client_context :: vSignal (
int ca_status, const char *pfilenm,
int lineno, const char *pFormat, va_list args )
{
static const char *severity[] =
{
"Warning",
"Success",
"Error",
"Info",
"Fatal",
"Fatal",
"Fatal",
"Fatal"
};
this->printFormated ( "CA.Client.Exception...............................................\n" );
this->printFormated ( " %s: \"%s\"\n",
severity[ CA_EXTRACT_SEVERITY ( ca_status ) ],
ca_message ( ca_status ) );
if ( pFormat ) {
this->printFormated ( " Context: \"" );
this->varArgsPrintFormated ( pFormat, args );
this->printFormated ( "\"\n" );
}
if ( pfilenm ) {
this->printFormated ( " Source File: %s line %d\n",
pfilenm, lineno );
}
epicsTime current = epicsTime::getCurrent ();
char date[64];
current.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S.%f");
this->printFormated ( " Current Time: %s\n", date );
/*
* Terminate execution if unsuccessful
*/
if( ! ( ca_status & CA_M_SUCCESS ) &&
CA_EXTRACT_SEVERITY ( ca_status ) != CA_K_WARNING ){
errlogFlush ();
abort ();
}
this->printFormated ( "..................................................................\n" );
}
void ca_client_context::show ( unsigned level ) const
{
epicsGuard < epicsMutex > guard ( this->mutex );
::printf ( "ca_client_context at %p pndRecvCnt=%u ioSeqNo=%u\n",
static_cast <const void *> ( this ),
this->pndRecvCnt, this->ioSeqNo );
if ( level > 0u ) {
this->pServiceContext->show ( guard, level - 1u );
::printf ( "\tpreemptive callback is %s\n",
this->pCallbackGuard.get() ? "disabled" : "enabled" );
::printf ( "\tthere are %u unsatisfied IO operations blocking ca_pend_io()\n",
this->pndRecvCnt );
::printf ( "\tthe current io sequence number is %u\n",
this->ioSeqNo );
::printf ( "IO done event:\n");
this->ioDone.show ( level - 1u );
::printf ( "Synchronous group identifier hash table:\n" );
this->sgTable.show ( level - 1u );
}
}
void ca_client_context::attachToClientCtx ()
{
assert ( ! epicsThreadPrivateGet ( caClientContextId ) );
epicsThreadPrivateSet ( caClientContextId, this );
}
void ca_client_context::incrementOutstandingIO (
epicsGuard < epicsMutex > & guard, unsigned ioSeqNoIn )
{
guard.assertIdenticalMutex ( this->mutex );
if ( this->ioSeqNo == ioSeqNoIn ) {
assert ( this->pndRecvCnt < UINT_MAX );
this->pndRecvCnt++;
}
}
void ca_client_context::decrementOutstandingIO (
epicsGuard < epicsMutex > & guard, unsigned ioSeqNoIn )
{
guard.assertIdenticalMutex ( this->mutex );
if ( this->ioSeqNo == ioSeqNoIn ) {
assert ( this->pndRecvCnt > 0u );
this->pndRecvCnt--;
if ( this->pndRecvCnt == 0u ) {
this->ioDone.signal ();
}
}
}
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! is disabled. This prevents the preemptive callback lock from being released
// !!!! by other threads than the one that locked it.
//
int ca_client_context::pendIO ( const double & timeout )
{
// prevent recursion nightmares by disabling calls to
// pendIO () from within a CA callback.
if ( epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
return ECA_EVDISALLOW;
}
int status = ECA_NORMAL;
epicsTime beg_time = epicsTime::getCurrent ();
double remaining = timeout;
epicsGuard < epicsMutex > guard ( this->mutex );
this->flush ( guard );
while ( this->pndRecvCnt > 0 ) {
if ( remaining < CAC_SIGNIFICANT_DELAY ) {
status = ECA_TIMEOUT;
break;
}
{
epicsGuardRelease < epicsMutex > unguard ( guard );
this->blockForEventAndEnableCallbacks ( this->ioDone, remaining );
}
double delay = epicsTime::getCurrent () - beg_time;
if ( delay < timeout ) {
remaining = timeout - delay;
}
else {
remaining = 0.0;
}
}
this->ioSeqNo++;
this->pndRecvCnt = 0u;
return status;
}
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! is disabled. This prevents the preemptive callback lock from being released
// !!!! by other threads than the one that locked it.
//
int ca_client_context::pendEvent ( const double & timeout )
{
// prevent recursion nightmares by disabling calls to
// pendIO () from within a CA callback.
if ( epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
return ECA_EVDISALLOW;
}
epicsTime current = epicsTime::getCurrent ();
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->flush ( guard );
}
// process at least once if preemptive callback is disabled
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < epicsMutex > cbUnguard ( *this->pCallbackGuard );
epicsGuard < epicsMutex > guard ( this->mutex );
//
// This is needed because in non-preemptive callback mode
// legacy applications that use file descriptor managers
// will register for ca receive thread activity and keep
// calling ca_pend_event until all of the socket data has
// been read. We must guarantee that other threads get a
// chance to run if there is data in any of the sockets.
//
if ( this->fdRegFunc ) {
epicsGuardRelease < epicsMutex > unguard ( guard );
// remove short udp message sent to wake
// up a file descriptor manager
osiSockAddr tmpAddr;
osiSocklen_t addrSize = sizeof ( tmpAddr.sa );
char buf = 0;
int status = 0;
do {
status = recvfrom ( this->sock, & buf, sizeof ( buf ),
0, & tmpAddr.sa, & addrSize );
} while ( status > 0 );
}
while ( this->callbackThreadsPending > 0 ) {
epicsGuardRelease < epicsMutex > unguard ( guard );
this->callbackThreadActivityComplete.wait ( 30.0 );
}
this->noWakeupSincePend = true;
}
double elapsed = epicsTime::getCurrent() - current;
double delay;
if ( timeout > elapsed ) {
delay = timeout - elapsed;
}
else {
delay = 0.0;
}
if ( delay >= CAC_SIGNIFICANT_DELAY ) {
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < epicsMutex > unguard ( *this->pCallbackGuard );
epicsThreadSleep ( delay );
}
else {
epicsThreadSleep ( delay );
}
}
return ECA_TIMEOUT;
}
void ca_client_context::blockForEventAndEnableCallbacks (
epicsEvent & event, const double & timeout )
{
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < epicsMutex > unguard ( *this->pCallbackGuard );
event.wait ( timeout );
}
else {
event.wait ( timeout );
}
}
void ca_client_context::callbackProcessingInitiateNotify ()
{
// if preemptive callback is enabled then this is a noop
if ( this->pCallbackGuard.get() ) {
bool sendNeeded = false;
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->callbackThreadsPending++;
if ( this->fdRegFunc && this->noWakeupSincePend ) {
this->noWakeupSincePend = false;
sendNeeded = true;
}
}
if ( sendNeeded ) {
_sendWakeupMsg ();
}
}
}
void ca_client_context :: _sendWakeupMsg ()
{
// send short udp message to wake up a file descriptor manager
// when a message arrives
osiSockAddr tmpAddr;
tmpAddr.ia.sin_family = AF_INET;
tmpAddr.ia.sin_addr.s_addr = htonl ( INADDR_LOOPBACK );
tmpAddr.ia.sin_port = htons ( this->localPort );
char buf = 0;
sendto ( this->sock, & buf, sizeof ( buf ),
0, & tmpAddr.sa, sizeof ( tmpAddr.sa ) );
}
void ca_client_context::callbackProcessingCompleteNotify ()
{
// if preemptive callback is enabled then this is a noop
if ( this->pCallbackGuard.get() ) {
bool signalNeeded = false;
{
epicsGuard < epicsMutex > guard ( this->mutex );
if ( this->callbackThreadsPending <= 1 ) {
if ( this->callbackThreadsPending == 1 ) {
this->callbackThreadsPending = 0;
signalNeeded = true;
}
}
else {
this->callbackThreadsPending--;
}
}
if ( signalNeeded ) {
this->callbackThreadActivityComplete.signal ();
}
}
}
cacChannel & ca_client_context::createChannel (
epicsGuard < epicsMutex > & guard, const char * pChannelName,
cacChannelNotify & chan, cacChannel::priLev pri )
{
guard.assertIdenticalMutex ( this->mutex );
return this->pServiceContext->createChannel (
guard, pChannelName, chan, pri );
}
void ca_client_context::flush ( epicsGuard < epicsMutex > & guard )
{
this->pServiceContext->flush ( guard );
}
unsigned ca_client_context::circuitCount () const
{
epicsGuard < epicsMutex > guard ( this->mutex );
return this->pServiceContext->circuitCount ( guard );
}
unsigned ca_client_context::beaconAnomaliesSinceProgramStart () const
{
epicsGuard < epicsMutex > guard ( this->mutex );
return this->pServiceContext->beaconAnomaliesSinceProgramStart ( guard );
}
void ca_client_context::installCASG (
epicsGuard < epicsMutex > & guard, CASG & sg )
{
guard.assertIdenticalMutex ( this->mutex );
this->sgTable.idAssignAdd ( sg );
}
void ca_client_context::uninstallCASG (
epicsGuard < epicsMutex > & guard, CASG & sg )
{
guard.assertIdenticalMutex ( this->mutex );
this->sgTable.remove ( sg );
}
CASG * ca_client_context::lookupCASG (
epicsGuard < epicsMutex > & guard, unsigned idIn )
{
guard.assertIdenticalMutex ( this->mutex );
CASG * psg = this->sgTable.lookup ( idIn );
if ( psg ) {
if ( ! psg->verify ( guard ) ) {
psg = 0;
}
}
return psg;
}
void ca_client_context::selfTest () const
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->sgTable.verify ();
this->pServiceContext->selfTest ( guard );
}
epicsMutex & ca_client_context::mutexRef () const
{
return this->mutex;
}
cacContext & ca_client_context::createNetworkContext (
epicsMutex & mutexIn, epicsMutex & cbMutexIn )
{
return * new cac ( mutexIn, cbMutexIn, *this );
}
void ca_client_context::installDefaultService ( cacService & service )
{
epicsThreadOnce ( & cacOnce, cacOnceFunc, 0 );
epicsGuard < epicsMutex > guard ( *ca_client_context::pDefaultServiceInstallMutex );
if ( ca_client_context::pDefaultService ) {
throw std::logic_error
( "CA in-memory service already installed and can't be replaced");
}
ca_client_context::pDefaultService = & service;
}
void epicsShareAPI caInstallDefaultService ( cacService & service )
{
ca_client_context::installDefaultService ( service );
}
epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
{
oldChannelNotify & chan = pMon->channel ();
ca_client_context & cac = chan.getClientCtx ();
// !!!! the order in which we take the mutex here prevents deadlocks
{
epicsGuard < epicsMutex > guard ( cac.mutex );
try {
// if this stalls out on a live circuit then an exception
// can be forthcoming which we must ignore as the clear
// request must always be successful
chan.eliminateExcessiveSendBacklog ( guard );
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored
}
}
if ( cac.pCallbackGuard.get() &&
cac.createdByThread == epicsThreadGetIdSelf () ) {
epicsGuard < epicsMutex > guard ( cac.mutex );
pMon->cancel ( *cac.pCallbackGuard.get(), guard );
}
else {
//
// we will definately stall out here if all of the
// following are true
//
// o user creates non-preemtive mode client library context
// o user doesnt periodically call a ca function
// o user calls this function from an auxiillary thread
//
CallbackGuard cbGuard ( cac.cbMutex );
epicsGuard < epicsMutex > guard ( cac.mutex );
pMon->cancel ( cbGuard, guard );
}
return ECA_NORMAL;
}
void ca_client_context :: eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > & guard, cacChannel & chan )
{
if ( chan.requestMessageBytesPending ( guard ) >
ca_client_context :: flushBlockThreshold ) {
if ( this->pCallbackGuard.get() &&
this->createdByThread == epicsThreadGetIdSelf () ) {
// we need to be very careful about lock hierarchy
// inversion in this situation
epicsGuardRelease < epicsMutex > unguard ( guard );
{
epicsGuardRelease < epicsMutex > cbunguard (
* this->pCallbackGuard.get() );
{
epicsGuard < epicsMutex > nestedGuard ( this->mutex );
chan.flush ( nestedGuard );
}
}
}
else {
chan.flush ( guard );
}
}
}

1324
src/ca/client/cac.cpp Normal file

File diff suppressed because it is too large Load Diff

467
src/ca/client/cac.h Normal file
View File

@@ -0,0 +1,467 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author: Jeff Hill
*
*/
#ifndef cach
#define cach
#ifdef epicsExportSharedSymbols
# define cach_restore_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include "compilerDependencies.h"
#include "ipAddrToAsciiAsynchronous.h"
#include "msgForMultiplyDefinedPV.h"
#include "epicsTimer.h"
#include "epicsEvent.h"
#include "freeList.h"
#include "localHostName.h"
#ifdef cach_restore_epicsExportSharedSymbols
# define epicsExportSharedSymbols
# include "shareLib.h"
#endif
#include "nciu.h"
#include "comBuf.h"
#include "bhe.h"
#include "cacIO.h"
#include "netIO.h"
#include "localHostName.h"
#include "virtualCircuit.h"
class netWriteNotifyIO;
class netReadNotifyIO;
class netSubscription;
// used to control access to cac's recycle routines which
// should only be indirectly invoked by CAC when its lock
// is applied
class cacRecycle {
public:
virtual void recycleReadNotifyIO (
epicsGuard < epicsMutex > &, netReadNotifyIO &io ) = 0;
virtual void recycleWriteNotifyIO (
epicsGuard < epicsMutex > &, netWriteNotifyIO &io ) = 0;
virtual void recycleSubscription (
epicsGuard < epicsMutex > &, netSubscription &io ) = 0;
protected:
virtual ~cacRecycle() {}
};
struct CASG;
class inetAddrID;
class caServerID;
struct caHdrLargeArray;
class cacComBufMemoryManager : public comBufMemoryManager
{
public:
cacComBufMemoryManager () {}
void * allocate ( size_t );
void release ( void * );
private:
tsFreeList < comBuf, 0x20 > freeList;
cacComBufMemoryManager ( const cacComBufMemoryManager & );
cacComBufMemoryManager & operator = ( const cacComBufMemoryManager & );
};
class notifyGuard {
public:
notifyGuard ( cacContextNotify & );
~notifyGuard ();
private:
cacContextNotify & notify;
notifyGuard ( const notifyGuard & );
notifyGuard & operator = ( const notifyGuard & );
};
class callbackManager : public notifyGuard {
public:
callbackManager (
cacContextNotify &,
epicsMutex & callbackControl );
epicsGuard < epicsMutex > cbGuard;
};
class cac :
public cacContext,
private cacRecycle,
private callbackForMultiplyDefinedPV
{
public:
cac (
epicsMutex & mutualExclusion,
epicsMutex & callbackControl,
cacContextNotify & );
virtual ~cac ();
// beacon management
void beaconNotify ( const inetAddrID & addr, const epicsTime & currentTime,
ca_uint32_t beaconNumber, unsigned protocolRevision );
unsigned beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & ) const;
// IO management
void flush ( epicsGuard < epicsMutex > & guard );
bool executeResponse ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, caHdrLargeArray &, char *pMsgBody );
// channel routines
void transferChanToVirtCircuit (
unsigned cid, unsigned sid,
ca_uint16_t typeCode, arrayElementCount count,
unsigned minorVersionNumber, const osiSockAddr &,
const epicsTime & currentTime );
cacChannel & createChannel (
epicsGuard < epicsMutex > & guard, const char * pChannelName,
cacChannelNotify &, cacChannel::priLev );
void destroyChannel (
epicsGuard < epicsMutex > &, nciu & );
void initiateConnect (
epicsGuard < epicsMutex > &, nciu &, netiiu * & );
nciu * lookupChannel (
epicsGuard < epicsMutex > &, const cacChannel::ioid & );
// IO requests
netWriteNotifyIO & writeNotifyRequest (
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
unsigned type, arrayElementCount nElem, const void * pValue,
cacWriteNotify & );
netReadNotifyIO & readNotifyRequest (
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
unsigned type, arrayElementCount nElem,
cacReadNotify & );
netSubscription & subscriptionRequest (
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
unsigned type, arrayElementCount nElem, unsigned mask,
cacStateNotify &, bool channelIsInstalled );
bool destroyIO (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const cacChannel::ioid & idIn,
nciu & chan );
void disconnectAllIO (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
nciu &, tsDLList < baseNMIU > & ioList );
void ioShow (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid &id, unsigned level ) const;
// exception generation
void exception (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
const char * pFileName, unsigned lineNo );
// search destination management
void registerSearchDest (
epicsGuard < epicsMutex > &, SearchDest & req );
bool findOrCreateVirtCircuit (
epicsGuard < epicsMutex > &, const osiSockAddr &,
unsigned, tcpiiu *&, unsigned, SearchDestTCP * pSearchDest = NULL );
// diagnostics
unsigned circuitCount ( epicsGuard < epicsMutex > & ) const;
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
int printFormated (
epicsGuard < epicsMutex > & callbackControl,
const char *pformat, ... ) const;
int varArgsPrintFormated (
epicsGuard < epicsMutex > & callbackControl,
const char *pformat, va_list args ) const;
double connectionTimeout ( epicsGuard < epicsMutex > & );
// buffer management
char * allocateSmallBufferTCP ();
void releaseSmallBufferTCP ( char * );
unsigned largeBufferSizeTCP () const;
char * allocateLargeBufferTCP ();
void releaseLargeBufferTCP ( char * );
unsigned maxContiguousFrames ( epicsGuard < epicsMutex > & ) const;
// misc
const char * userNamePointer () const;
unsigned getInitializingThreadsPriority () const;
epicsMutex & mutexRef ();
void attachToClientCtx ();
void selfTest (
epicsGuard < epicsMutex > & ) const;
double beaconPeriod (
epicsGuard < epicsMutex > &,
const nciu & chan ) const;
static unsigned lowestPriorityLevelAbove ( unsigned priority );
static unsigned highestPriorityLevelBelow ( unsigned priority );
void destroyIIU ( tcpiiu & iiu );
const char * pLocalHostName ();
private:
epicsSingleton < localHostName > :: reference _refLocalHostName;
chronIntIdResTable < nciu > chanTable;
//
// !!!! There is at this point no good reason
// !!!! to maintain one IO table for all types of
// !!!! IO. It would probably be better to maintain
// !!!! an independent table for each IO type. The
// !!!! new adaptive sized hash table will not
// !!!! waste memory. Making this change will
// !!!! avoid virtual function overhead when
// !!!! accessing the different types of IO. This
// !!!! approach would also probably be safer in
// !!!! terms of detecting damaged protocol.
//
chronIntIdResTable < baseNMIU > ioTable;
resTable < bhe, inetAddrID > beaconTable;
resTable < tcpiiu, caServerID > serverTable;
tsDLList < tcpiiu > circuitList;
tsDLList < SearchDest > searchDestList;
tsDLList < msgForMultiplyDefinedPV > msgMultiPVList;
tsFreeList
< class tcpiiu, 32, epicsMutexNOOP >
freeListVirtualCircuit;
tsFreeList
< class netReadNotifyIO, 1024, epicsMutexNOOP >
freeListReadNotifyIO;
tsFreeList
< class netWriteNotifyIO, 1024, epicsMutexNOOP >
freeListWriteNotifyIO;
tsFreeList
< class netSubscription, 1024, epicsMutexNOOP >
freeListSubscription;
tsFreeList
< class nciu, 1024, epicsMutexNOOP >
channelFreeList;
tsFreeList
< class msgForMultiplyDefinedPV, 16 >
mdpvFreeList;
cacComBufMemoryManager comBufMemMgr;
bheFreeStore bheFreeList;
epicsTime programBeginTime;
double connTMO;
// **** lock hierarchy ****
// 1) callback lock must always be acquired before
// the primary mutex if both locks are needed
epicsMutex & mutex;
epicsMutex & cbMutex;
epicsEvent iiuUninstall;
ipAddrToAsciiEngine & ipToAEngine;
epicsTimerQueueActive & timerQueue;
char * pUserName;
class udpiiu * pudpiiu;
void * tcpSmallRecvBufFreeList;
void * tcpLargeRecvBufFreeList;
cacContextNotify & notify;
epicsThreadId initializingThreadsId;
unsigned initializingThreadsPriority;
unsigned maxRecvBytesTCP;
unsigned maxContigFrames;
unsigned beaconAnomalyCount;
unsigned short _serverPort;
unsigned iiuExistenceCount;
bool cacShutdownInProgress;
void recycleReadNotifyIO (
epicsGuard < epicsMutex > &, netReadNotifyIO &io );
void recycleWriteNotifyIO (
epicsGuard < epicsMutex > &, netWriteNotifyIO &io );
void recycleSubscription (
epicsGuard < epicsMutex > &, netSubscription &io );
void disconnectChannel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard, nciu & chan );
void ioExceptionNotify ( unsigned id, int status,
const char * pContext, unsigned type, arrayElementCount count );
void ioExceptionNotifyAndUninstall ( unsigned id, int status,
const char * pContext, unsigned type, arrayElementCount count );
void pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
const char * pChannelName, const char * pAcc, const char * pRej );
// recv protocol stubs
bool versionAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool echoRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool writeNotifyRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool searchRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool readNotifyRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool eventRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool readRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool clearChannelRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool exceptionRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool accessRightsRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool createChannelRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool verifyAndDisconnectChan ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool badTCPRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
typedef bool ( cac::*pProtoStubTCP ) (
callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
static const pProtoStubTCP tcpJumpTableCAC [];
bool defaultExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool eventAddExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool readExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool writeExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool clearChanExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool readNotifyExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool writeNotifyExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
typedef bool ( cac::*pExcepProtoStubTCP ) (
callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
static const pExcepProtoStubTCP tcpExcepJumpTableCAC [];
cac ( const cac & );
cac & operator = ( const cac & );
};
inline const char * cac::userNamePointer () const
{
return this->pUserName;
}
inline unsigned cac::getInitializingThreadsPriority () const
{
return this->initializingThreadsPriority;
}
inline epicsMutex & cac::mutexRef ()
{
return this->mutex;
}
inline int cac :: varArgsPrintFormated (
epicsGuard < epicsMutex > & callbackControl,
const char *pformat, va_list args ) const
{
callbackControl.assertIdenticalMutex ( this->cbMutex );
return this->notify.varArgsPrintFormated ( pformat, args );
}
inline void cac::attachToClientCtx ()
{
this->notify.attachToClientCtx ();
}
inline char * cac::allocateSmallBufferTCP ()
{
// this locks internally
return ( char * ) freeListMalloc ( this->tcpSmallRecvBufFreeList );
}
inline void cac::releaseSmallBufferTCP ( char *pBuf )
{
// this locks internally
freeListFree ( this->tcpSmallRecvBufFreeList, pBuf );
}
inline unsigned cac::largeBufferSizeTCP () const
{
return this->maxRecvBytesTCP;
}
inline char * cac::allocateLargeBufferTCP ()
{
// this locks internally
return ( char * ) freeListMalloc ( this->tcpLargeRecvBufFreeList );
}
inline void cac::releaseLargeBufferTCP ( char *pBuf )
{
// this locks internally
freeListFree ( this->tcpLargeRecvBufFreeList, pBuf );
}
inline unsigned cac::beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & guard ) const
{
guard.assertIdenticalMutex ( this->mutex );
return this->beaconAnomalyCount;
}
inline notifyGuard::notifyGuard ( cacContextNotify & notifyIn ) :
notify ( notifyIn )
{
this->notify.callbackProcessingInitiateNotify ();
}
inline notifyGuard::~notifyGuard ()
{
this->notify.callbackProcessingCompleteNotify ();
}
inline callbackManager::callbackManager (
cacContextNotify & notify, epicsMutex & callbackControl ) :
notifyGuard ( notify ), cbGuard ( callbackControl )
{
}
inline nciu * cac::lookupChannel (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & idIn )
{
guard.assertIdenticalMutex ( this->mutex );
return this->chanTable.lookup ( idIn );
}
inline const char * cac :: pLocalHostName ()
{
return _refLocalHostName->pointer ();
}
inline unsigned cac ::
maxContiguousFrames ( epicsGuard < epicsMutex > & ) const
{
return maxContigFrames;
}
inline double cac ::
connectionTimeout ( epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
return this->connTMO;
}
#endif // ifdef cach

View File

@@ -0,0 +1,145 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#include <stdexcept>
#include <float.h>
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "errlog.h"
#define epicsExportSharedSymbols
#include "iocinf.h"
#include "localHostName.h"
#include "cacIO.h"
class CACChannelPrivate {
public:
CACChannelPrivate ();
unsigned getHostName ( char * pBuf, unsigned bufLength );
const char * pHostName ();
private:
epicsSingleton < localHostName > :: reference
_refLocalHostName;
};
static epicsThreadOnceId cacChannelIdOnce = EPICS_THREAD_ONCE_INIT;
const cacChannel::priLev cacChannel::priorityMax = 99u;
const cacChannel::priLev cacChannel::priorityMin = 0u;
const cacChannel::priLev cacChannel::priorityDefault = priorityMin;
const cacChannel::priLev cacChannel::priorityLinksDB = priorityMax;
const cacChannel::priLev cacChannel::priorityArchive = ( priorityMax - priorityMin ) / 2;
const cacChannel::priLev cacChannel::priorityOPI = priorityMin;
cacChannel::~cacChannel ()
{
}
caAccessRights cacChannel::accessRights (
epicsGuard < epicsMutex > & ) const
{
static caAccessRights ar ( true, true );
return ar;
}
unsigned cacChannel::searchAttempts (
epicsGuard < epicsMutex > & ) const
{
return 0u;
}
double cacChannel::beaconPeriod (
epicsGuard < epicsMutex > & ) const
{
return - DBL_MAX;
}
double cacChannel::receiveWatchdogDelay (
epicsGuard < epicsMutex > & ) const
{
return - DBL_MAX;
}
bool cacChannel::ca_v42_ok (
epicsGuard < epicsMutex > & ) const
{
return true;
}
bool cacChannel::connected (
epicsGuard < epicsMutex > & ) const
{
return true;
}
CACChannelPrivate ::
CACChannelPrivate() :
_refLocalHostName ( localHostNameCache.getReference () )
{
}
inline unsigned CACChannelPrivate ::
getHostName ( char * pBuf, unsigned bufLength )
{
return _refLocalHostName->getName ( pBuf, bufLength );
}
inline const char * CACChannelPrivate ::
pHostName ()
{
return _refLocalHostName->pointer ();
}
static CACChannelPrivate * pCACChannelPrivate = 0;
// runs once only for each process
extern "C" void cacChannelSetup ( void * )
{
pCACChannelPrivate = new CACChannelPrivate ();
}
// the default is to assume that it is a locally hosted channel
unsigned cacChannel::getHostName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLength ) const throw ()
{
if ( bufLength ) {
epicsThreadOnce ( & cacChannelIdOnce, cacChannelSetup, 0);
return pCACChannelPrivate->getHostName ( pBuf, bufLength );
}
return 0u;
}
// the default is to assume that it is a locally hosted channel
const char * cacChannel::pHostName (
epicsGuard < epicsMutex > & ) const throw ()
{
epicsThreadOnce ( & cacChannelIdOnce, cacChannelSetup, 0);
return pCACChannelPrivate->pHostName ();
}
cacContext::~cacContext () {}
cacService::~cacService () {}

View File

@@ -0,0 +1,34 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include "iocinf.h"
#define epicsExportSharedSymbols
#include "cacIO.h"
#undef epicsExportSharedSymbols
cacChannelNotify::~cacChannelNotify ()
{
}

View File

@@ -0,0 +1,43 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#include <stdlib.h>
#include "iocinf.h"
#define epicsExportSharedSymbols
#include "cacIO.h"
#undef epicsExportSharedSymbols
cacContextNotify::~cacContextNotify ()
{
}
void cacContextNotify::callbackProcessingInitiateNotify ()
{
}
void cacContextNotify::callbackProcessingCompleteNotify ()
{
}

392
src/ca/client/cacIO.h Normal file
View File

@@ -0,0 +1,392 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifndef cacIOh
#define cacIOh
//
// Open Issues
// -----------
//
// 1) A status code from the old client side interface is passed
// to the exception notify callback. Should we just pass a string?
// If so, then how do they detect the type of error and recover.
// Perhaps we should call a different vf for each type of exception.
//
// 2) Some exception types are present here but there is no common
// exception base class in use.
//
// 3) Should I be passing the channel reference in cacChannelNotify?
//
// 4) Should the code for caAccessRights not be inline so that this
// interface is version independent.
//
//
#include <new>
#include <stdarg.h>
#ifdef epicsExportSharedSymbols
# define cacIOh_restore_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include "tsDLList.h"
#include "epicsMutex.h"
#include "epicsGuard.h"
#include "epicsThread.h"
#ifdef cacIOh_restore_epicsExportSharedSymbols
# define epicsExportSharedSymbols
# include "shareLib.h"
#endif
class cacChannel;
typedef unsigned long arrayElementCount;
// 1) this should not be passing caerr.h status to the exception callback
// 2) needless-to-say the data should be passed here using the new data access API
class epicsShareClass cacWriteNotify {
public:
virtual ~cacWriteNotify () = 0;
virtual void completion ( epicsGuard < epicsMutex > & ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
epicsGuard < epicsMutex > &,
int status, const char * pContext,
unsigned type, arrayElementCount count ) = 0;
};
// 1) this should not be passing caerr.h status to the exception callback
// 2) needless-to-say the data should be passed here using the new data access API
class epicsShareClass cacReadNotify {
public:
virtual ~cacReadNotify () = 0;
virtual void completion (
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void * pData ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
epicsGuard < epicsMutex > &, int status,
const char * pContext, unsigned type,
arrayElementCount count ) = 0;
};
// 1) this should not be passing caerr.h status to the exception callback
// 2) needless-to-say the data should be passed here using the new data access API
class epicsShareClass cacStateNotify {
public:
virtual ~cacStateNotify () = 0;
virtual void current (
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void * pData ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
epicsGuard < epicsMutex > &, int status,
const char *pContext, unsigned type,
arrayElementCount count ) = 0;
};
class caAccessRights {
public:
caAccessRights (
bool readPermit = false,
bool writePermit = false,
bool operatorConfirmationRequest = false);
void setReadPermit ();
void setWritePermit ();
void setOperatorConfirmationRequest ();
void clrReadPermit ();
void clrWritePermit ();
void clrOperatorConfirmationRequest ();
bool readPermit () const;
bool writePermit () const;
bool operatorConfirmationRequest () const;
private:
bool f_readPermit:1;
bool f_writePermit:1;
bool f_operatorConfirmationRequest:1;
};
class epicsShareClass cacChannelNotify {
public:
virtual ~cacChannelNotify () = 0;
virtual void connectNotify ( epicsGuard < epicsMutex > & ) = 0;
virtual void disconnectNotify ( epicsGuard < epicsMutex > & ) = 0;
virtual void serviceShutdownNotify (
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
virtual void accessRightsNotify (
epicsGuard < epicsMutex > &, const caAccessRights & ) = 0;
virtual void exception (
epicsGuard < epicsMutex > &, int status, const char *pContext ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void readException (
epicsGuard < epicsMutex > &, int status, const char *pContext,
unsigned type, arrayElementCount count, void *pValue ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void writeException (
epicsGuard < epicsMutex > &, int status, const char * pContext,
unsigned type, arrayElementCount count ) = 0;
};
class CallbackGuard :
public epicsGuard < epicsMutex > {
public:
CallbackGuard ( epicsMutex & mutex ) :
epicsGuard < epicsMutex > ( mutex ) {}
private:
CallbackGuard ( const CallbackGuard & );
CallbackGuard & operator = ( const CallbackGuard & );
};
//
// Notes
// 1) This interface assumes that when a channel is deleted then all
// attached IO is deleted. This is left over from the old interface,
// but perhaps is a bad practice that should be eliminated? If so,
// then the IO should not store or use a pointer to the channel.
//
class epicsShareClass cacChannel {
public:
typedef unsigned priLev;
static const priLev priorityMax;
static const priLev priorityMin;
static const priLev priorityDefault;
static const priLev priorityLinksDB;
static const priLev priorityArchive;
static const priLev priorityOPI;
typedef unsigned ioid;
enum ioStatus { iosSynch, iosAsynch };
cacChannel ( cacChannelNotify & );
virtual void destroy (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
cacChannelNotify & notify () const; // required ?????
virtual unsigned getName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLen ) const throw () = 0;
// !! deprecated, avoid use !!
virtual const char * pName (
epicsGuard < epicsMutex > & guard ) const throw () = 0;
virtual void show (
epicsGuard < epicsMutex > &,
unsigned level ) const = 0;
virtual void initiateConnect (
epicsGuard < epicsMutex > & ) = 0;
virtual unsigned requestMessageBytesPending (
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
virtual void flush (
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
virtual ioStatus read (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
cacReadNotify &, ioid * = 0 ) = 0;
virtual void write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
const void *pValue ) = 0;
virtual ioStatus write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
const void *pValue, cacWriteNotify &, ioid * = 0 ) = 0;
virtual void subscribe (
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, unsigned mask, cacStateNotify &,
ioid * = 0 ) = 0;
// The primary mutex must be released when calling the user's
// callback, and therefore a finite interval exists when we are
// moving forward with the intent to call the users callback
// but the users IO could be deleted during this interval.
// To prevent the user's callback from being called after
// destroying his IO we must past a guard for the callback
// mutex here.
virtual void ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & ) = 0;
virtual void ioShow (
epicsGuard < epicsMutex > &,
const ioid &, unsigned level ) const = 0;
virtual short nativeType (
epicsGuard < epicsMutex > & ) const = 0;
virtual arrayElementCount nativeElementCount (
epicsGuard < epicsMutex > & ) const = 0;
virtual caAccessRights accessRights (
epicsGuard < epicsMutex > & ) const;
virtual unsigned searchAttempts (
epicsGuard < epicsMutex > & ) const;
virtual double beaconPeriod (
epicsGuard < epicsMutex > & ) const; // negative DBL_MAX if UKN
virtual double receiveWatchdogDelay (
epicsGuard < epicsMutex > & ) const; // negative DBL_MAX if UKN
virtual bool ca_v42_ok (
epicsGuard < epicsMutex > & ) const;
virtual bool connected (
epicsGuard < epicsMutex > & ) const;
virtual unsigned getHostName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLength ) const throw ();
// !! deprecated, avoid use !!
virtual const char * pHostName (
epicsGuard < epicsMutex > & guard ) const throw ();
// exceptions
class badString {};
class badType {};
class badPriority {};
class outOfBounds {};
class badEventSelection {};
class noWriteAccess {};
class noReadAccess {};
class notConnected {};
class unsupportedByService {};
class msgBodyCacheTooSmall {}; // hopefully this one goes away in the future
class requestTimedOut {};
protected:
virtual ~cacChannel () = 0;
private:
cacChannelNotify & callback;
cacChannel ( const cacChannel & );
cacChannel & operator = ( const cacChannel & );
};
class epicsShareClass cacContext {
public:
virtual ~cacContext ();
virtual cacChannel & createChannel (
epicsGuard < epicsMutex > &,
const char * pChannelName, cacChannelNotify &,
cacChannel::priLev = cacChannel::priorityDefault ) = 0;
virtual void flush (
epicsGuard < epicsMutex > & ) = 0;
virtual unsigned circuitCount (
epicsGuard < epicsMutex > & ) const = 0;
virtual void selfTest (
epicsGuard < epicsMutex > & ) const = 0;
virtual unsigned beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & ) const = 0;
virtual void show (
epicsGuard < epicsMutex > &, unsigned level ) const = 0;
};
class epicsShareClass cacContextNotify {
public:
virtual ~cacContextNotify () = 0;
virtual cacContext & createNetworkContext (
epicsMutex & mutualExclusion, epicsMutex & callbackControl ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo ) = 0;
// perhaps this should be phased out in deference to the exception mechanism
virtual int varArgsPrintFormated ( const char * pformat, va_list args ) const = 0;
// backwards compatibility (from here down)
virtual void attachToClientCtx () = 0;
virtual void callbackProcessingInitiateNotify () = 0;
virtual void callbackProcessingCompleteNotify () = 0;
};
// **** Lock Hierarchy ****
// callbackControl must be taken before mutualExclusion if both are held at
// the same time
class epicsShareClass cacService {
public:
virtual ~cacService () = 0;
virtual cacContext & contextCreate (
epicsMutex & mutualExclusion,
epicsMutex & callbackControl,
cacContextNotify & ) = 0;
};
epicsShareFunc void epicsShareAPI caInstallDefaultService ( cacService & service );
epicsShareExtern epicsThreadPrivateId caClientCallbackThreadId;
inline cacChannel::cacChannel ( cacChannelNotify & notify ) :
callback ( notify )
{
}
inline cacChannelNotify & cacChannel::notify () const
{
return this->callback;
}
inline caAccessRights::caAccessRights (
bool readPermit, bool writePermit, bool operatorConfirmationRequest) :
f_readPermit ( readPermit ), f_writePermit ( writePermit ),
f_operatorConfirmationRequest ( operatorConfirmationRequest ) {}
inline void caAccessRights::setReadPermit ()
{
this->f_readPermit = true;
}
inline void caAccessRights::setWritePermit ()
{
this->f_writePermit = true;
}
inline void caAccessRights::setOperatorConfirmationRequest ()
{
this->f_operatorConfirmationRequest = true;
}
inline void caAccessRights::clrReadPermit ()
{
this->f_readPermit = false;
}
inline void caAccessRights::clrWritePermit ()
{
this->f_writePermit = false;
}
inline void caAccessRights::clrOperatorConfirmationRequest ()
{
this->f_operatorConfirmationRequest = false;
}
inline bool caAccessRights::readPermit () const
{
return this->f_readPermit;
}
inline bool caAccessRights::writePermit () const
{
return this->f_writePermit;
}
inline bool caAccessRights::operatorConfirmationRequest () const
{
return this->f_operatorConfirmationRequest;
}
#endif // ifndef cacIOh

View File

@@ -0,0 +1,30 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#include "iocinf.h"
#define epicsExportSharedSymbols
#include "cacIO.h"
#undef epicsExportSharedSymbols
cacReadNotify::~cacReadNotify ()
{
}

View File

@@ -0,0 +1,30 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#include "iocinf.h"
#define epicsExportSharedSymbols
#include "cacIO.h"
#undef epicsExportSharedSymbols
cacStateNotify::~cacStateNotify ()
{
}

View File

@@ -0,0 +1,30 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#include "iocinf.h"
#define epicsExportSharedSymbols
#include "cacIO.h"
#undef epicsExportSharedSymbols
cacWriteNotify::~cacWriteNotify ()
{
}

904
src/ca/client/cadef.h Normal file
View File

@@ -0,0 +1,904 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*
*/
#ifndef INCLcadefh
#define INCLcadefh
/*
* done in two ifdef steps so that we will remain compatible with
* traditional C
*/
#ifndef CA_DONT_INCLUDE_STDARGH
# include <stdarg.h>
#endif
#ifdef epicsExportSharedSymbols
# define INCLcadefh_accessh_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include "epicsThread.h"
#ifdef INCLcadefh_accessh_epicsExportSharedSymbols
# define epicsExportSharedSymbols
# include "shareLib.h"
#endif
#include "caerr.h"
#include "db_access.h"
#include "caeventmask.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct oldChannelNotify *chid;
typedef chid chanId; /* for when the structures field name is "chid" */
typedef long chtype;
typedef struct oldSubscription *evid;
typedef double ca_real;
/* arguments passed to user connection handlers */
struct connection_handler_args {
chanId chid; /* channel id */
long op; /* one of CA_OP_CONN_UP or CA_OP_CONN_DOWN */
};
typedef void caCh (struct connection_handler_args args);
typedef struct ca_access_rights {
unsigned read_access:1;
unsigned write_access:1;
} caar;
/* arguments passed to user access rights handlers */
struct access_rights_handler_args {
chanId chid; /* channel id */
caar ar; /* new access rights state */
};
typedef void caArh (struct access_rights_handler_args args);
/* The conversion routine to call for each type */
#define VALID_TYPE(TYPE) (((unsigned short)TYPE)<=LAST_BUFFER_TYPE)
/*
* Arguments passed to event handlers and get/put call back handlers.
*
* The status field below is the CA ECA_XXX status of the requested
* operation which is saved from when the operation was attempted in the
* server and copied back to the clients call back routine.
* If the status is not ECA_NORMAL then the dbr pointer will be NULL
* and the requested operation can not be assumed to be successful.
*/
typedef struct event_handler_args {
void *usr; /* user argument supplied with request */
chanId chid; /* channel id */
long type; /* the type of the item returned */
long count; /* the element count of the item returned */
const void *dbr; /* a pointer to the item returned */
int status; /* ECA_XXX status of the requested op from the server */
} evargs;
typedef void caEventCallBackFunc (struct event_handler_args);
epicsShareFunc void epicsShareAPI ca_test_event
(
struct event_handler_args
);
/* arguments passed to user exception handlers */
struct exception_handler_args {
void *usr; /* user argument supplied when installed */
chanId chid; /* channel id (may be nill) */
long type; /* type requested */
long count; /* count requested */
void *addr; /* user's address to write results of CA_OP_GET */
long stat; /* channel access ECA_XXXX status code */
long op; /* CA_OP_GET, CA_OP_PUT, ..., CA_OP_OTHER */
const char *ctx; /* a character string containing context info */
const char *pFile; /* source file name (may be NULL) */
unsigned lineNo; /* source file line number (may be zero) */
};
typedef unsigned CA_SYNC_GID;
/*
* External OP codes for CA operations
*/
#define CA_OP_GET 0
#define CA_OP_PUT 1
#define CA_OP_CREATE_CHANNEL 2
#define CA_OP_ADD_EVENT 3
#define CA_OP_CLEAR_EVENT 4
#define CA_OP_OTHER 5
/*
* used with connection_handler_args
*/
#define CA_OP_CONN_UP 6
#define CA_OP_CONN_DOWN 7
/* depricated */
#define CA_OP_SEARCH 2
/*
* provides efficient test and display of channel access errors
*/
#define SEVCHK(CA_ERROR_CODE, MESSAGE_STRING) \
{ \
int ca_unique_status_name = (CA_ERROR_CODE); \
if(!(ca_unique_status_name & CA_M_SUCCESS)) \
ca_signal_with_file_and_lineno( \
ca_unique_status_name, \
(MESSAGE_STRING), \
__FILE__, \
__LINE__); \
}
#define TYPENOTCONN (-1) /* the channel's native type when disconnected */
epicsShareFunc short epicsShareAPI ca_field_type (chid chan);
epicsShareFunc unsigned long epicsShareAPI ca_element_count (chid chan);
epicsShareFunc const char * epicsShareAPI ca_name (chid chan);
epicsShareFunc void epicsShareAPI ca_set_puser (chid chan, void *puser);
epicsShareFunc void * epicsShareAPI ca_puser (chid chan);
epicsShareFunc unsigned epicsShareAPI ca_read_access (chid chan);
epicsShareFunc unsigned epicsShareAPI ca_write_access (chid chan);
/*
* cs_ - `channel state'
*
* cs_never_conn valid chid, IOC not found
* cs_prev_conn valid chid, IOC was found, but unavailable
* cs_conn valid chid, IOC was found, still available
* cs_closed channel deleted by user
*/
enum channel_state {cs_never_conn, cs_prev_conn, cs_conn, cs_closed};
epicsShareFunc enum channel_state epicsShareAPI ca_state (chid chan);
/************************************************************************/
/* Perform Library Initialization */
/* */
/* Must be called once before calling any of the other routines */
/************************************************************************/
epicsShareFunc int epicsShareAPI ca_task_initialize (void);
enum ca_preemptive_callback_select
{ ca_disable_preemptive_callback, ca_enable_preemptive_callback };
epicsShareFunc int epicsShareAPI
ca_context_create (enum ca_preemptive_callback_select select);
epicsShareFunc void epicsShareAPI ca_detach_context ();
/************************************************************************/
/* Remove CA facility from your task */
/* */
/* Normally called automatically at task exit */
/************************************************************************/
epicsShareFunc int epicsShareAPI ca_task_exit (void);
epicsShareFunc void epicsShareAPI ca_context_destroy (void);
typedef unsigned capri;
#define CA_PRIORITY_MAX 99
#define CA_PRIORITY_MIN 0
#define CA_PRIORITY_DEFAULT CA_PRIORITY_MIN
#define CA_PRIORITY_DB_LINKS 80
#define CA_PRIORITY_ARCHIVE 20
#define CA_PRIORITY_OPI 0
/*
* ca_create_channel ()
*
* pChanName R channel name string
* pConnStateCallback R address of connection state change
* callback function
* pUserPrivate R placed in the channel's user private field
* o can be fetched later by ca_puser(CHID)
* o passed as void * arg to *pConnectCallback above
* priority R priority level in the server 0 - 100
* pChanID RW channel id written here
*/
epicsShareFunc int epicsShareAPI ca_create_channel
(
const char *pChanName,
caCh *pConnStateCallback,
void *pUserPrivate,
capri priority,
chid *pChanID
);
/*
* ca_change_connection_event()
*
* chan R channel identifier
* pfunc R address of connection call-back function
*/
epicsShareFunc int epicsShareAPI ca_change_connection_event
(
chid chan,
caCh * pfunc
);
/*
* ca_replace_access_rights_event ()
*
* chan R channel identifier
* pfunc R address of access rights call-back function
*/
epicsShareFunc int epicsShareAPI ca_replace_access_rights_event (
chid chan,
caArh *pfunc
);
/*
* ca_add_exception_event ()
*
* replace the default exception handler
*
* pfunc R address of exception call-back function
* pArg R copy of this pointer passed to exception
* call-back function
*/
typedef void caExceptionHandler (struct exception_handler_args);
epicsShareFunc int epicsShareAPI ca_add_exception_event
(
caExceptionHandler *pfunc,
void *pArg
);
/*
* ca_clear_channel()
* - deallocate resources reserved for a channel
*
* chanId R channel ID
*/
epicsShareFunc int epicsShareAPI ca_clear_channel
(
chid chanId
);
/************************************************************************/
/* Write a value to a channel */
/************************************************************************/
/*
* ca_bput()
*
* WARNING: this copies the new value from a string (dbr_string_t)
* (and not as an integer)
*
* chan R channel identifier
* pValue R new channel value string copied from this location
*/
#define ca_bput(chan, pValue) \
ca_array_put(DBR_STRING, 1u, chan, (const dbr_string_t *) (pValue))
/*
* ca_rput()
*
* WARNING: this copies the new value from a dbr_float_t
*
* chan R channel identifier
* pValue R new channel value copied from this location
*/
#define ca_rput(chan,pValue) \
ca_array_put(DBR_FLOAT, 1u, chan, (const dbr_float_t *) pValue)
/*
* ca_put()
*
* type R data type from db_access.h
* chan R channel identifier
* pValue R new channel value copied from this location
*/
#define ca_put(type, chan, pValue) ca_array_put (type, 1u, chan, pValue)
/*
* ca_array_put()
*
* type R data type from db_access.h
* count R array element count
* chan R channel identifier
* pValue R new channel value copied from this location
*/
epicsShareFunc int epicsShareAPI ca_array_put
(
chtype type,
unsigned long count,
chid chanId,
const void * pValue
);
/*
* ca_array_put_callback()
*
* This routine functions identically to the original ca put request
* with the addition of a callback to the user supplied function
* after recod processing completes in the IOC. The arguments
* to the user supplied callback function are declared in
* the structure event_handler_args and include the pointer
* sized user argument supplied when ca_array_put_callback() is called.
*
* type R data type from db_access.h
* count R array element count
* chan R channel identifier
* pValue R new channel value copied from this location
* pFunc R pointer to call-back function
* pArg R copy of this pointer passed to pFunc
*/
epicsShareFunc int epicsShareAPI ca_array_put_callback
(
chtype type,
unsigned long count,
chid chanId,
const void * pValue,
caEventCallBackFunc * pFunc,
void * pArg
);
#define ca_put_callback(type, chan, pValue, pFunc, pArg) \
ca_array_put_callback(type, 1u, chan, pValue, pFunc, pArg)
/************************************************************************/
/* Read a value from a channel */
/************************************************************************/
/*
* ca_bget()
*
* WARNING: this copies the new value into a string (dbr_string_t)
* (and not into an integer)
*
* chan R channel identifier
* pValue W channel value copied to this location
*/
#define ca_bget(chan, pValue) \
ca_array_get(DBR_STRING, 1u, chan, (dbr_string_t *)(pValue))
/*
* ca_rget()
*
* WARNING: this copies the new value into a 32 bit float (dbr_float_t)
*
* chan R channel identifier
* pValue W channel value copied to this location
*/
#define ca_rget(chan, pValue) \
ca_array_get(DBR_FLOAT, 1u, chan, (dbr_float_t *)(pValue))
/*
* ca_rget()
*
* type R data type from db_access.h
* chan R channel identifier
* pValue W channel value copied to this location
*/
#define ca_get(type, chan, pValue) ca_array_get(type, 1u, chan, pValue)
/*
* ca_array_get()
*
* type R data type from db_access.h
* count R array element count
* chan R channel identifier
* pValue W channel value copied to this location
*/
epicsShareFunc int epicsShareAPI ca_array_get
(
chtype type,
unsigned long count,
chid chanId,
void * pValue
);
/************************************************************************/
/* Read a value from a channel and run a callback when the value */
/* returns */
/* */
/* */
/************************************************************************/
/*
* ca_bget_callback()
*
* WARNING: this returns the new value as a string (dbr_string_t)
* (and not as an integer)
*
* chan R channel identifier
* pFunc R pointer to call-back function
* pArg R copy of this pointer passed to pFunc
*/
#define ca_bget_callback(chan, pFunc, pArg)\
ca_array_get_callback (DBR_STRING, 1u, chan, pFunc, pArg)
/*
* ca_rget_callback()
*
* WARNING: this returns the new value as a float (dbr_float_t)
*
* chan R channel identifier
* pFunc R pointer to call-back function
* pArg R copy of this pointer passed to pFunc
*/
#define ca_rget_callback(chan, pFunc, pArg)\
ca_array_get_callback (DBR_FLOAT, 1u, chan, pFunc, pArg)
/*
* ca_get_callback()
*
* type R data type from db_access.h
* chan R channel identifier
* pFunc R pointer to call-back function
* pArg R copy of this pointer passed to pFunc
*/
#define ca_get_callback(type, chan, pFunc, pArg)\
ca_array_get_callback (type, 1u, chan, pFunc, pArg)
/*
* ca_array_get_callback()
*
* type R data type from db_access.h
* count R array element count
* chan R channel identifier
* pFunc R pointer to call-back function
* pArg R copy of this pointer passed to pFunc
*/
epicsShareFunc int epicsShareAPI ca_array_get_callback
(
chtype type,
unsigned long count,
chid chanId,
caEventCallBackFunc * pFunc,
void * pArg
);
/************************************************************************/
/* Specify a function to be executed whenever significant changes */
/* occur to a channel. */
/* NOTES: */
/* 1) Evid may be omited by passing a NULL pointer */
/* */
/* 2) An array count of zero specifies the native db count */
/* */
/************************************************************************/
/*
* ca_create_subscription ()
*
* type R data type from db_access.h
* count R array element count
* chan R channel identifier
* mask R event mask - one of {DBE_VALUE, DBE_ALARM, DBE_LOG}
* pFunc R pointer to call-back function
* pArg R copy of this pointer passed to pFunc
* pEventID W event id written at specified address
*/
epicsShareFunc int epicsShareAPI ca_create_subscription
(
chtype type,
unsigned long count,
chid chanId,
long mask,
caEventCallBackFunc * pFunc,
void * pArg,
evid * pEventID
);
/************************************************************************/
/* Remove a function from a list of those specified to run */
/* whenever significant changes occur to a channel */
/* */
/************************************************************************/
/*
* ca_clear_subscription()
*
* eventID R event id
*/
epicsShareFunc int epicsShareAPI ca_clear_subscription
(
evid eventID
);
epicsShareFunc chid epicsShareAPI ca_evid_to_chid ( evid id );
/************************************************************************/
/* */
/* Requested data is not necessarily stable prior to */
/* return from called subroutine. Call ca_pend_io() */
/* to guarantee that requested data is stable. Call the routine */
/* ca_flush_io() to force all outstanding requests to be */
/* sent out over the network. Significant increases in */
/* performance have been measured when batching several remote */
/* requests together into one message. Additional */
/* improvements can be obtained by performing local processing */
/* in parallel with outstanding remote processing. */
/* */
/* FLOW OF TYPICAL APPLICATION */
/* */
/* search() ! Obtain Channel ids */
/* . ! " */
/* . ! " */
/* pend_io ! wait for channels to connect */
/* */
/* get() ! several requests for remote info */
/* get() ! " */
/* add_event() ! " */
/* get() ! " */
/* . */
/* . */
/* . */
/* flush_io() ! send get requests */
/* ! optional parallel processing */
/* . ! " */
/* . ! " */
/* pend_io() ! wait for replies from get requests */
/* . ! access to requested data */
/* . ! " */
/* pend_event() ! wait for requested events */
/* */
/************************************************************************/
/************************************************************************/
/* These routines wait for channel subscription events and call the */
/* functions specified with add_event when events occur. If the */
/* timeout is specified as 0 an infinite timeout is assumed. */
/* ca_flush_io() is called by this routine. If ca_pend_io () */
/* is called when no IO is outstanding then it will return immediately */
/* without processing. */
/************************************************************************/
/*
* ca_pend_event()
*
* timeOut R wait for this delay in seconds
*/
epicsShareFunc int epicsShareAPI ca_pend_event (ca_real timeOut);
#define ca_poll() ca_pend_event(1e-12)
/*
* ca_pend_io()
*
* timeOut R wait for this delay in seconds but return early
* if all get requests (or search requests with null
* connection handler pointer have completed)
*/
epicsShareFunc int epicsShareAPI ca_pend_io (ca_real timeOut);
/* calls ca_pend_io() if early is true otherwise ca_pend_event() is called */
epicsShareFunc int epicsShareAPI ca_pend (ca_real timeout, int early);
/*
* ca_test_io()
*
* returns TRUE when get requests (or search requests with null
* connection handler pointer) are outstanding
*/
epicsShareFunc int epicsShareAPI ca_test_io (void);
/************************************************************************/
/* Send out all outstanding messages in the send queue */
/************************************************************************/
/*
* ca_flush_io()
*/
epicsShareFunc int epicsShareAPI ca_flush_io (void);
/*
* ca_signal()
*
* errorCode R status returned from channel access function
* pCtxStr R context string included with error print out
*/
epicsShareFunc void epicsShareAPI ca_signal
(
long errorCode,
const char *pCtxStr
);
/*
* ca_signal_with_file_and_lineno()
* errorCode R status returned from channel access function
* pCtxStr R context string included with error print out
* pFileStr R file name string included with error print out
* lineNo R line number included with error print out
*
*/
epicsShareFunc void epicsShareAPI ca_signal_with_file_and_lineno
(
long errorCode,
const char *pCtxStr,
const char *pFileStr,
int lineNo
);
/*
* ca_signal_formated()
* errorCode R status returned from channel access function
* pFileStr R file name string included with error print out
* lineNo R line number included with error print out
* pFormat R printf dtyle format string (and optional arguments)
*
*/
epicsShareFunc void epicsShareAPI ca_signal_formated (long ca_status, const char *pfilenm,
int lineno, const char *pFormat, ...);
/*
* ca_host_name_function()
*
* channel R channel identifier
*
* !!!! this function is _not_ thread safe !!!!
*/
epicsShareFunc const char * epicsShareAPI ca_host_name (chid channel);
/* thread safe version */
epicsShareFunc unsigned epicsShareAPI ca_get_host_name ( chid pChan,
char *pBuf, unsigned bufLength );
/*
* CA_ADD_FD_REGISTRATION
*
* call their function with their argument whenever
* a new fd is added or removed
* (for use with a manager of the select system call under UNIX)
*
* if (opened) then fd was created
* if (!opened) then fd was deleted
*
*/
typedef void CAFDHANDLER (void *parg, int fd, int opened);
/*
* ca_add_fd_registration()
*
* pHandler R pointer to function which is to be called
* when an fd is created or deleted
* pArg R argument passed to above function
*/
epicsShareFunc int epicsShareAPI ca_add_fd_registration
(
CAFDHANDLER *pHandler,
void *pArg
);
/*
* CA synch groups
*
* This facility will allow the programmer to create
* any number of synchronization groups. The programmer might then
* interleave IO requests within any of the groups. Once The
* IO operations are initiated then the programmer is free to
* block for IO completion within any one of the groups as needed.
*/
/*
* ca_sg_create()
*
* create a sync group
*
* pgid W pointer to sync group id that will be written
*/
epicsShareFunc int epicsShareAPI ca_sg_create (CA_SYNC_GID * pgid);
/*
* ca_sg_delete()
*
* delete a sync group
*
* gid R sync group id
*/
epicsShareFunc int epicsShareAPI ca_sg_delete (const CA_SYNC_GID gid);
/*
* ca_sg_block()
*
* block for IO performed within a sync group to complete
*
* gid R sync group id
* timeout R wait for this duration prior to timing out
* and returning ECA_TIMEOUT
*/
epicsShareFunc int epicsShareAPI ca_sg_block (const CA_SYNC_GID gid, ca_real timeout);
/*
* ca_sg_test()
*
* test for sync group IO operations in progress
*
* gid R sync group id
*
* returns one of ECA_BADSYNCGRP, ECA_IOINPROGRESS, ECA_IODONE
*/
epicsShareFunc int epicsShareAPI ca_sg_test (const CA_SYNC_GID gid);
/*
* ca_sg_reset
*
* gid R sync group id
*/
epicsShareFunc int epicsShareAPI ca_sg_reset(const CA_SYNC_GID gid);
/*
* ca_sg_array_get()
*
* initiate a get within a sync group
* (essentially a ca_array_get() with a sync group specified)
*
* gid R sync group id
* type R data type from db_access.h
* count R array element count
* chan R channel identifier
* pValue W channel value copied to this location
*/
epicsShareFunc int epicsShareAPI ca_sg_array_get
(
const CA_SYNC_GID gid,
chtype type,
unsigned long count,
chid chan,
void *pValue
);
#define ca_sg_get(gid, type, chan, pValue) \
ca_sg_array_get (gid, type, 1u, chan, pValue)
/*
* ca_sg_array_put()
*
* initiate a put within a sync group
* (essentially a ca_array_put() with a sync group specified)
*
* gid R sync group id
* type R data type from db_access.h
* count R array element count
* chan R channel identifier
* pValue R new channel value copied from this location
*/
epicsShareFunc int epicsShareAPI ca_sg_array_put
(
const CA_SYNC_GID gid,
chtype type,
unsigned long count,
chid chan,
const void *pValue
);
#define ca_sg_put(gid, type, chan, pValue) \
ca_sg_array_put (gid, type, 1u, chan, pValue)
/*
* ca_sg_stat()
*
* print status of a sync group
*
* gid R sync group id
*/
epicsShareFunc int epicsShareAPI ca_sg_stat (CA_SYNC_GID gid);
epicsShareFunc void epicsShareAPI ca_dump_dbr (chtype type, unsigned count, const void * pbuffer);
/*
* ca_v42_ok()
*
* Put call back is available if the CA server is on version is 4.2
* or higher.
*
* chan R channel identifier
*
* (returns true or false)
*/
epicsShareFunc int epicsShareAPI ca_v42_ok (chid chan);
/*
* ca_version()
*
* returns the CA version string
*/
epicsShareFunc const char * epicsShareAPI ca_version (void);
/*
* ca_replace_printf_handler ()
*
* for apps that want to change where ca formatted
* text output goes
*
* use two ifdef's for trad C compatibility
*
* ca_printf_func R pointer to new function called when
* CA prints an error message
*/
#ifndef CA_DONT_INCLUDE_STDARGH
typedef int caPrintfFunc (const char *pformat, va_list args);
epicsShareFunc int epicsShareAPI ca_replace_printf_handler (
caPrintfFunc *ca_printf_func
);
#endif /*CA_DONT_INCLUDE_STDARGH*/
/*
* (for testing purposes only)
*/
epicsShareFunc unsigned epicsShareAPI ca_get_ioc_connection_count (void);
epicsShareFunc int epicsShareAPI ca_preemtive_callback_is_enabled (void);
epicsShareFunc void epicsShareAPI ca_self_test (void);
epicsShareFunc unsigned epicsShareAPI ca_beacon_anomaly_count (void);
epicsShareFunc unsigned epicsShareAPI ca_search_attempts (chid chan);
epicsShareFunc double epicsShareAPI ca_beacon_period (chid chan);
epicsShareFunc double epicsShareAPI ca_receive_watchdog_delay (chid chan);
/*
* used when an auxillary thread needs to join a CA client context started
* by another thread
*/
epicsShareFunc struct ca_client_context * epicsShareAPI ca_current_context ();
epicsShareFunc int epicsShareAPI ca_attach_context ( struct ca_client_context * context );
epicsShareFunc int epicsShareAPI ca_client_status ( unsigned level );
epicsShareFunc int epicsShareAPI ca_context_status ( struct ca_client_context *, unsigned level );
/*
* deprecated
*/
#define ca_build_channel(NAME,XXXXX,CHIDPTR,YYYYY)\
ca_build_and_connect(NAME, XXXXX, 1, CHIDPTR, YYYYY, 0, 0)
#define ca_array_build(NAME,XXXXX, ZZZZZZ, CHIDPTR,YYYYY)\
ca_build_and_connect(NAME, XXXXX, ZZZZZZ, CHIDPTR, YYYYY, 0, 0)
epicsShareFunc int epicsShareAPI ca_build_and_connect
( const char *pChanName, chtype, unsigned long,
chid * pChanID, void *, caCh * pFunc, void * pArg );
#define ca_search(pChanName, pChanID)\
ca_search_and_connect (pChanName, pChanID, 0, 0)
epicsShareFunc int epicsShareAPI ca_search_and_connect
( const char * pChanName, chid * pChanID,
caCh *pFunc, void * pArg );
epicsShareFunc int epicsShareAPI ca_channel_status (epicsThreadId tid);
epicsShareFunc int epicsShareAPI ca_clear_event ( evid eventID );
#define ca_add_event(type,chan,pFunc,pArg,pEventID)\
ca_add_array_event(type,1u,chan,pFunc,pArg,0.0,0.0,0.0,pEventID)
#define ca_add_delta_event(TYPE,CHID,ENTRY,ARG,DELTA,EVID)\
ca_add_array_event(TYPE,1,CHID,ENTRY,ARG,DELTA,DELTA,0.0,EVID)
#define ca_add_general_event(TYPE,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID)\
ca_add_array_event(TYPE,1,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID)
#define ca_add_array_event(TYPE,COUNT,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID)\
ca_add_masked_array_event(TYPE,COUNT,CHID,ENTRY,ARG,P_DELTA,N_DELTA,TO,EVID, DBE_VALUE | DBE_ALARM)
epicsShareFunc int epicsShareAPI ca_add_masked_array_event
( chtype type, unsigned long count, chid chanId, caEventCallBackFunc * pFunc,
void * pArg, ca_real p_delta, ca_real n_delta, ca_real timeout,
evid * pEventID, long mask );
/*
* defunct
*/
epicsShareFunc int epicsShareAPI ca_modify_user_name ( const char *pUserName );
epicsShareFunc int epicsShareAPI ca_modify_host_name ( const char *pHostName );
#ifdef __cplusplus
}
#endif
/*
* no additions below this endif
*/
#endif /* ifndef INCLcadefh */

160
src/ca/client/caerr.h Normal file
View File

@@ -0,0 +1,160 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeffrey O. Hill
*
*/
#ifndef INCLcaerrh
#define INCLcaerrh
#ifdef epicsExportSharedSymbols
# define INCLcaerrh_accessh_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
# include "epicsTypes.h"
#ifdef INCLcaerrh_accessh_epicsExportSharedSymbols
# define epicsExportSharedSymbols
# include "shareLib.h"
#endif
/* CA Status Code Definitions */
#define CA_K_INFO 3 /* successful */
#define CA_K_ERROR 2 /* failed- continue */
#define CA_K_SUCCESS 1 /* successful */
#define CA_K_WARNING 0 /* unsuccessful */
#define CA_K_SEVERE 4 /* failed- quit */
#define CA_K_FATAL CA_K_ERROR | CA_K_SEVERE
#define CA_M_MSG_NO 0x0000FFF8
#define CA_M_SEVERITY 0x00000007
#define CA_M_LEVEL 0x00000003
#define CA_M_SUCCESS 0x00000001
#define CA_M_ERROR 0x00000002
#define CA_M_SEVERE 0x00000004
#define CA_S_MSG_NO 0x0D
#define CA_S_SEVERITY 0x03
#define CA_V_MSG_NO 0x03
#define CA_V_SEVERITY 0x00
#define CA_V_SUCCESS 0x00
/* Define MACROS to extract/insert individual fields from a status value */
#define CA_EXTRACT_MSG_NO(code)\
( ( (code) & CA_M_MSG_NO ) >> CA_V_MSG_NO )
#define CA_EXTRACT_SEVERITY(code)\
( ( (code) & CA_M_SEVERITY ) >> CA_V_SEVERITY )
#define CA_EXTRACT_SUCCESS(code)\
( ( (code) & CA_M_SUCCESS ) >> CA_V_SUCCESS )
#define CA_INSERT_MSG_NO(code)\
( ((code)<< CA_V_MSG_NO) & CA_M_MSG_NO )
#define CA_INSERT_SEVERITY(code)\
( ((code)<< CA_V_SEVERITY)& CA_M_SEVERITY )
#define CA_INSERT_SUCCESS(code)\
( ((code)<< CA_V_SUCCESS) & CA_M_SUCCESS )
#define DEFMSG(SEVERITY,NUMBER)\
(CA_INSERT_MSG_NO(NUMBER) | CA_INSERT_SEVERITY(SEVERITY))
/*
* In the lines below "defunct" indicates that current release
* servers and client library will not return this error code, but
* servers on earlier releases that communicate with current clients
* might still generate exceptions with these error constants
*/
#define ECA_NORMAL DEFMSG(CA_K_SUCCESS, 0) /* success */
#define ECA_MAXIOC DEFMSG(CA_K_ERROR, 1) /* defunct */
#define ECA_UKNHOST DEFMSG(CA_K_ERROR, 2) /* defunct */
#define ECA_UKNSERV DEFMSG(CA_K_ERROR, 3) /* defunct */
#define ECA_SOCK DEFMSG(CA_K_ERROR, 4) /* defunct */
#define ECA_CONN DEFMSG(CA_K_WARNING, 5) /* defunct */
#define ECA_ALLOCMEM DEFMSG(CA_K_WARNING, 6)
#define ECA_UKNCHAN DEFMSG(CA_K_WARNING, 7) /* defunct */
#define ECA_UKNFIELD DEFMSG(CA_K_WARNING, 8) /* defunct */
#define ECA_TOLARGE DEFMSG(CA_K_WARNING, 9)
#define ECA_TIMEOUT DEFMSG(CA_K_WARNING, 10)
#define ECA_NOSUPPORT DEFMSG(CA_K_WARNING, 11) /* defunct */
#define ECA_STRTOBIG DEFMSG(CA_K_WARNING, 12) /* defunct */
#define ECA_DISCONNCHID DEFMSG(CA_K_ERROR, 13) /* defunct */
#define ECA_BADTYPE DEFMSG(CA_K_ERROR, 14)
#define ECA_CHIDNOTFND DEFMSG(CA_K_INFO, 15) /* defunct */
#define ECA_CHIDRETRY DEFMSG(CA_K_INFO, 16) /* defunct */
#define ECA_INTERNAL DEFMSG(CA_K_FATAL, 17)
#define ECA_DBLCLFAIL DEFMSG(CA_K_WARNING, 18) /* defunct */
#define ECA_GETFAIL DEFMSG(CA_K_WARNING, 19)
#define ECA_PUTFAIL DEFMSG(CA_K_WARNING, 20)
#define ECA_ADDFAIL DEFMSG(CA_K_WARNING, 21) /* defunct */
#define ECA_BADCOUNT DEFMSG(CA_K_WARNING, 22)
#define ECA_BADSTR DEFMSG(CA_K_ERROR, 23)
#define ECA_DISCONN DEFMSG(CA_K_WARNING, 24)
#define ECA_DBLCHNL DEFMSG(CA_K_WARNING, 25)
#define ECA_EVDISALLOW DEFMSG(CA_K_ERROR, 26)
#define ECA_BUILDGET DEFMSG(CA_K_WARNING, 27) /* defunct */
#define ECA_NEEDSFP DEFMSG(CA_K_WARNING, 28) /* defunct */
#define ECA_OVEVFAIL DEFMSG(CA_K_WARNING, 29) /* defunct */
#define ECA_BADMONID DEFMSG(CA_K_ERROR, 30)
#define ECA_NEWADDR DEFMSG(CA_K_WARNING, 31) /* defunct */
#define ECA_NEWCONN DEFMSG(CA_K_INFO, 32) /* defunct */
#define ECA_NOCACTX DEFMSG(CA_K_WARNING, 33) /* defunct */
#define ECA_DEFUNCT DEFMSG(CA_K_FATAL, 34) /* defunct */
#define ECA_EMPTYSTR DEFMSG(CA_K_WARNING, 35) /* defunct */
#define ECA_NOREPEATER DEFMSG(CA_K_WARNING, 36) /* defunct */
#define ECA_NOCHANMSG DEFMSG(CA_K_WARNING, 37) /* defunct */
#define ECA_DLCKREST DEFMSG(CA_K_WARNING, 38) /* defunct */
#define ECA_SERVBEHIND DEFMSG(CA_K_WARNING, 39) /* defunct */
#define ECA_NOCAST DEFMSG(CA_K_WARNING, 40) /* defunct */
#define ECA_BADMASK DEFMSG(CA_K_ERROR, 41)
#define ECA_IODONE DEFMSG(CA_K_INFO, 42)
#define ECA_IOINPROGRESS DEFMSG(CA_K_INFO, 43)
#define ECA_BADSYNCGRP DEFMSG(CA_K_ERROR, 44)
#define ECA_PUTCBINPROG DEFMSG(CA_K_ERROR, 45)
#define ECA_NORDACCESS DEFMSG(CA_K_WARNING, 46)
#define ECA_NOWTACCESS DEFMSG(CA_K_WARNING, 47)
#define ECA_ANACHRONISM DEFMSG(CA_K_ERROR, 48)
#define ECA_NOSEARCHADDR DEFMSG(CA_K_WARNING, 49)
#define ECA_NOCONVERT DEFMSG(CA_K_WARNING, 50)
#define ECA_BADCHID DEFMSG(CA_K_ERROR, 51)
#define ECA_BADFUNCPTR DEFMSG(CA_K_ERROR, 52)
#define ECA_ISATTACHED DEFMSG(CA_K_WARNING, 53)
#define ECA_UNAVAILINSERV DEFMSG(CA_K_WARNING, 54)
#define ECA_CHANDESTROY DEFMSG(CA_K_WARNING, 55)
#define ECA_BADPRIORITY DEFMSG(CA_K_ERROR, 56)
#define ECA_NOTTHREADED DEFMSG(CA_K_ERROR, 57)
#define ECA_16KARRAYCLIENT DEFMSG(CA_K_WARNING, 58)
#define ECA_CONNSEQTMO DEFMSG(CA_K_WARNING, 59)
#define ECA_UNRESPTMO DEFMSG(CA_K_WARNING, 60)
#ifdef __cplusplus
extern "C" {
#endif
epicsShareFunc const char * epicsShareAPI ca_message(long ca_status);
epicsShareExtern const char * ca_message_text [];
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,44 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef INCLcaeventmaskh
#define INCLcaeventmaskh
/*
event selections
(If any more than 8 of these are needed then update the
select field in the event_block struct in db_event.c from
unsigned char to unsigned short)
DBE_VALUE
Trigger an event when a significant change in the channel's value
occurs. Relies on the monitor deadband field under DCT.
DBE_ARCHIVE (DBE_LOG)
Trigger an event when an archive significant change in the channel's
value occurs. Relies on the archiver monitor deadband field under DCT.
DBE_ALARM
Trigger an event when the alarm state changes
DBE_PROPERTY
Trigger an event when a property change (control limit, graphical
limit, status string, enum string ...) occurs.
*/
#define DBE_VALUE (1<<0)
#define DBE_ARCHIVE (1<<1)
#define DBE_LOG DBE_ARCHIVE
#define DBE_ALARM (1<<2)
#define DBE_PROPERTY (1<<3)
#endif

306
src/ca/client/casw.cpp Normal file
View File

@@ -0,0 +1,306 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
* Author: Jeff Hill
*/
#include <stdio.h>
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "envDefs.h"
#include "errlog.h"
#include "osiWireFormat.h"
#include "bhe.h"
#include "udpiiu.h"
#include "inetAddrID.h"
// using a wrapper class around the free list avoids
// Tornado 2.0.1 GNU compiler bugs
class bheFreeStoreMgr : public bheMemoryManager {
public:
bheFreeStoreMgr () {}
void * allocate ( size_t );
void release ( void * );
private:
tsFreeList < class bhe, 0x100 > freeList;
bheFreeStoreMgr ( const bheFreeStoreMgr & );
bheFreeStoreMgr & operator = ( const bheFreeStoreMgr & );
};
void * bheFreeStoreMgr::allocate ( size_t size )
{
return freeList.allocate ( size );
}
void bheFreeStoreMgr::release ( void * pCadaver )
{
freeList.release ( pCadaver );
}
int main ( int argc, char ** argv )
{
epicsMutex mutex;
epicsGuard < epicsMutex > guard ( mutex );
bheFreeStoreMgr bheFreeList;
epicsTime programBeginTime = epicsTime::getCurrent ();
bool validCommandLine = false;
unsigned interest = 0u;
SOCKET sock;
osiSockAddr addr;
osiSocklen_t addrSize;
char buf [0x4000];
const char *pCurBuf;
const caHdr *pCurMsg;
ca_uint16_t serverPort;
ca_uint16_t repeaterPort;
int status;
if ( argc == 1 ) {
validCommandLine = true;
}
else if ( argc == 2 ) {
status = sscanf ( argv[1], " -i%u ", & interest );
if ( status == 1 ) {
validCommandLine = true;
}
}
else if ( argc == 3 ) {
if ( strcmp ( argv[1], "-i" ) == 0 ) {
status = sscanf ( argv[2], " %u ", & interest );
if ( status == 1 ) {
validCommandLine = true;
}
}
}
if ( ! validCommandLine ) {
printf ( "usage: casw <-i interestLevel>\n" );
return 0;
}
serverPort =
envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT,
static_cast <unsigned short> (CA_SERVER_PORT) );
repeaterPort =
envGetInetPortConfigParam ( &EPICS_CA_REPEATER_PORT,
static_cast <unsigned short> (CA_REPEATER_PORT) );
caStartRepeaterIfNotInstalled ( repeaterPort );
sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( sock == INVALID_SOCKET ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ("casw: unable to create datagram socket because = \"%s\"\n",
sockErrBuf );
return -1;
}
memset ( (char *) &addr, 0 , sizeof (addr) );
addr.ia.sin_family = AF_INET;
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
addr.ia.sin_port = htons ( 0 ); // any port
status = bind ( sock, &addr.sa, sizeof (addr) );
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
epicsSocketDestroy ( sock );
errlogPrintf ( "casw: unable to bind to an unconstrained address because = \"%s\"\n",
sockErrBuf );
return -1;
}
osiSockIoctl_t yes = true;
status = socket_ioctl ( sock, FIONBIO, &yes );
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
epicsSocketDestroy ( sock );
errlogPrintf ( "casw: unable to set socket to nonblocking state because \"%s\"\n",
sockErrBuf );
return -1;
}
unsigned attemptNumber = 0u;
while ( true ) {
caRepeaterRegistrationMessage ( sock, repeaterPort, attemptNumber );
epicsThreadSleep ( 0.1 );
addrSize = ( osiSocklen_t ) sizeof ( addr );
status = recvfrom ( sock, buf, sizeof ( buf ), 0,
&addr.sa, &addrSize );
if ( status >= static_cast <int> ( sizeof ( *pCurMsg ) ) ) {
pCurMsg = reinterpret_cast < caHdr * > ( buf );
epicsUInt16 cmmd = AlignedWireRef < const epicsUInt16 > ( pCurMsg->m_cmmd );
if ( cmmd == REPEATER_CONFIRM ) {
break;
}
}
attemptNumber++;
if ( attemptNumber > 100 ) {
epicsSocketDestroy ( sock );
errlogPrintf ( "casw: unable to register with the CA repeater\n" );
return -1;
}
}
osiSockIoctl_t no = false;
status = socket_ioctl ( sock, FIONBIO, &no );
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
epicsSocketDestroy ( sock );
errlogPrintf ( "casw: unable to set socket to blocking state because \"%s\"\n",
sockErrBuf );
return -1;
}
resTable < bhe, inetAddrID > beaconTable;
while ( true ) {
addrSize = ( osiSocklen_t ) sizeof ( addr );
status = recvfrom ( sock, buf, sizeof ( buf ), 0,
&addr.sa, &addrSize );
if ( status <= 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
epicsSocketDestroy ( sock );
errlogPrintf ("casw: error from recv was = \"%s\"\n",
sockErrBuf );
return -1;
}
if ( addr.sa.sa_family != AF_INET ) {
continue;
}
unsigned byteCount = static_cast <unsigned> ( status );
pCurMsg = reinterpret_cast < const caHdr * > ( ( pCurBuf = buf ) );
while ( byteCount ) {
AlignedWireRef < const epicsUInt16 > pstSize ( pCurMsg->m_postsize );
size_t msgSize = pstSize + sizeof ( *pCurMsg ) ;
if ( msgSize > byteCount ) {
errlogPrintf ( "CASW: udp input protocol violation\n" );
break;
}
epicsUInt16 cmmd = AlignedWireRef < const epicsUInt16 > ( pCurMsg->m_cmmd );
if ( cmmd == CA_PROTO_RSRV_IS_UP ) {
bool anomaly = false;
epicsTime previousTime;
struct sockaddr_in ina;
/*
* this allows a fan-out server to potentially
* insert the true address of the CA server
*
* old servers:
* 1) set this field to one of the ip addresses of the host _or_
* 2) set this field to INADDR_ANY
* new servers:
* always set this field to INADDR_ANY
*
* clients always assume that if this
* field is set to something that isnt INADDR_ANY
* then it is the overriding IP address of the server.
*/
ina.sin_family = AF_INET;
ina.sin_addr.s_addr = pCurMsg->m_available;
if ( pCurMsg->m_count != 0 ) {
ina.sin_port = pCurMsg->m_count;
}
else {
/*
* old servers dont supply this and the
* default port must be assumed
*/
ina.sin_port = htons ( serverPort );
}
ca_uint32_t beaconNumber = ntohl ( pCurMsg->m_cid );
unsigned protocolRevision = ntohs ( pCurMsg->m_dataType );
epicsTime currentTime = epicsTime::getCurrent();
/*
* look for it in the hash table
*/
bhe *pBHE = beaconTable.lookup ( ina );
if ( pBHE ) {
previousTime = pBHE->updateTime ( guard );
anomaly = pBHE->updatePeriod (
guard, programBeginTime,
currentTime, beaconNumber, protocolRevision );
}
else {
/*
* This is the first beacon seen from this server.
* 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)
*/
pBHE = new ( bheFreeList )
bhe ( mutex, currentTime, beaconNumber, ina );
if ( pBHE ) {
if ( beaconTable.add ( *pBHE ) < 0 ) {
pBHE->~bhe ();
bheFreeList.release ( pBHE );
}
}
}
if ( anomaly || interest > 1 ) {
char date[64];
currentTime.strftime ( date, sizeof ( date ),
"%Y-%m-%d %H:%M:%S.%09f");
char host[64];
ipAddrToA ( &ina, host, sizeof ( host ) );
const char * pPrefix = "";
if ( interest > 1 ) {
if ( anomaly ) {
pPrefix = "* ";
}
else {
pPrefix = " ";
}
}
printf ( "%s%-40s %s\n",
pPrefix, host, date );
if ( anomaly && interest > 0 ) {
printf ( "\testimate=%f current=%f\n",
pBHE->period ( guard ),
currentTime - previousTime );
}
fflush(stdout);
}
}
pCurBuf += msgSize;
pCurMsg = reinterpret_cast < const caHdr * > ( pCurBuf );
byteCount -= msgSize;
}
}
}

685
src/ca/client/catime.c Normal file
View File

@@ -0,0 +1,685 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
* CA performance test
*
* History
* joh 09-12-89 Initial release
* joh 12-20-94 portability
*
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "epicsAssert.h"
#include "epicsTime.h"
#include "cadef.h"
#include "caProto.h"
#include "caDiagnostics.h"
#ifndef NULL
#define NULL 0
#endif
#define WAIT_FOR_ACK
typedef struct testItem {
chid chix;
char name[128];
int type;
int count;
void * pValue;
} ti;
typedef void tf ( ti *pItems, unsigned iterations, unsigned *pInlineIter );
/*
* test_pend()
*/
static void test_pend(
ti *pItems,
unsigned iterations,
unsigned *pInlineIter
)
{
unsigned i;
int status;
for (i=0; i<iterations; i++) {
status = ca_pend_event(1e-9);
if (status != ECA_TIMEOUT && status != ECA_NORMAL) {
SEVCHK(status, NULL);
}
status = ca_pend_event(1e-9);
if (status != ECA_TIMEOUT && status != ECA_NORMAL) {
SEVCHK(status, NULL);
}
status = ca_pend_event(1e-9);
if (status != ECA_TIMEOUT && status != ECA_NORMAL) {
SEVCHK(status, NULL);
}
status = ca_pend_event(1e-9);
if (status != ECA_TIMEOUT && status != ECA_NORMAL) {
SEVCHK(status, NULL);
}
status = ca_pend_event(1e-9);
if (status != ECA_TIMEOUT && status != ECA_NORMAL) {
SEVCHK(status, NULL);
}
}
*pInlineIter = 5;
}
/*
* test_search ()
*/
static void test_search (
ti *pItems,
unsigned iterations,
unsigned *pInlineIter
)
{
unsigned i;
int status;
for ( i = 0u; i < iterations; i++ ) {
status = ca_search ( pItems[i].name, &pItems[i].chix );
SEVCHK (status, NULL);
}
status = ca_pend_io ( 0.0 );
SEVCHK ( status, NULL );
*pInlineIter = 1;
}
/*
* test_sync_search()
*/
#if 0
static void test_sync_search(
ti *pItems,
unsigned iterations,
unsigned *pInlineIter
)
{
unsigned i;
int status;
for (i=0u; i<iterations; i++) {
status = ca_search (pItems[i].name, &pItems[i].chix);
SEVCHK (status, NULL);
status = ca_pend_io(0.0);
SEVCHK (status, NULL);
}
*pInlineIter = 1;
}
#endif
/*
* test_free ()
*/
static void test_free(
ti *pItems,
unsigned iterations,
unsigned *pInlineIter
)
{
int status;
unsigned i;
for (i=0u; i<iterations; i++) {
status = ca_clear_channel (pItems[i].chix);
SEVCHK (status, NULL);
}
status = ca_flush_io();
SEVCHK (status, NULL);
*pInlineIter = 1;
}
/*
* test_put ()
*/
static void test_put(
ti *pItems,
unsigned iterations,
unsigned *pInlineIter
)
{
ti *pi;
int status;
dbr_int_t val;
for (pi=pItems; pi < &pItems[iterations]; pi++) {
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_put(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
}
#ifdef WAIT_FOR_ACK
status = ca_array_get (DBR_INT, 1, pItems[0].chix, &val);
SEVCHK (status, NULL);
ca_pend_io(100.0);
#endif
status = ca_array_put(
pItems[0].type,
pItems[0].count,
pItems[0].chix,
pItems[0].pValue);
SEVCHK (status, NULL);
status = ca_flush_io();
SEVCHK (status, NULL);
*pInlineIter = 10;
}
/*
* test_get ()
*/
static void test_get(
ti *pItems,
unsigned iterations,
unsigned *pInlineIter
)
{
ti *pi;
int status;
for (pi=pItems; pi<&pItems[iterations]; pi++) {
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
}
status = ca_pend_io(1e20);
SEVCHK (status, NULL);
*pInlineIter = 10;
}
/*
* test_wait ()
*/
static void test_wait (
ti *pItems,
unsigned iterations,
unsigned *pInlineIter
)
{
ti *pi;
int status;
for (pi=pItems; pi<&pItems[iterations]; pi++) {
status = ca_array_get(
pi->type,
pi->count,
pi->chix,
pi->pValue);
SEVCHK (status, NULL);
status = ca_pend_io(100.0);
SEVCHK (status, NULL);
}
*pInlineIter = 1;
}
/*
* measure_get_latency
*/
static void measure_get_latency (ti *pItems, unsigned iterations)
{
epicsTimeStamp end_time;
epicsTimeStamp start_time;
double delay;
double X = 0u;
double XX = 0u;
double max = DBL_MIN;
double min = DBL_MAX;
double mean;
double stdDev;
ti *pi;
int status;
for ( pi = pItems; pi < &pItems[iterations]; pi++ ) {
epicsTimeGetCurrent ( &start_time );
status = ca_array_get ( pi->type, pi->count,
pi->chix, pi->pValue );
SEVCHK ( status, NULL );
status = ca_pend_io ( 100.0 );
SEVCHK ( status, NULL );
epicsTimeGetCurrent ( &end_time );
delay = epicsTimeDiffInSeconds ( &end_time,&start_time );
X += delay;
XX += delay*delay;
if ( delay > max ) {
max = delay;
}
if ( delay < min ) {
min = delay;
}
}
mean = X/iterations;
stdDev = sqrt ( XX/iterations - mean*mean );
printf (
"Get Latency - "
"mean = %3.1f uS, "
"std dev = %3.1f uS, "
"min = %3.1f uS "
"max = %3.1f uS\n",
mean * 1e6, stdDev * 1e6,
min * 1e6, max * 1e6 );
}
/*
* printSearchStat()
*/
static void printSearchStat ( const ti * pi, unsigned iterations )
{
unsigned i;
double X = 0u;
double XX = 0u;
double max = DBL_MIN;
double min = DBL_MAX;
double mean;
double stdDev;
for ( i = 0; i < iterations; i++ ) {
double retry = ca_search_attempts ( pi[i].chix );
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 = %3.1f "
"std dev = %3.1f "
"min = %3.1f "
"max = %3.1f\n",
mean, stdDev, min, max);
}
/*
* timeIt ()
*/
void timeIt ( tf *pfunc, ti *pItems, unsigned iterations,
unsigned nBytesSent, unsigned nBytesRecv )
{
epicsTimeStamp end_time;
epicsTimeStamp start_time;
double delay;
unsigned inlineIter;
epicsTimeGetCurrent ( &start_time );
(*pfunc) ( pItems, iterations, &inlineIter );
epicsTimeGetCurrent ( &end_time );
delay = epicsTimeDiffInSeconds ( &end_time, &start_time );
if ( delay > 0.0 ) {
double freq = ( iterations * inlineIter ) / delay;
printf ( "Per Op, %8.4f uS ( %8.4f MHz )",
1e6 / freq, freq / 1e6 );
if ( pItems != NULL ) {
printf(", %8.4f snd Mbps, %8.4f rcv Mbps\n",
(inlineIter*nBytesSent*CHAR_BIT)/(delay*1e6),
(inlineIter*nBytesRecv*CHAR_BIT)/(delay*1e6) );
}
else {
printf ("\n");
}
}
}
/*
* test ()
*/
static void test ( ti *pItems, unsigned iterations )
{
unsigned payloadSize, dblPayloadSize;
unsigned nBytesSent, nBytesRecv;
payloadSize =
dbr_size_n ( pItems[0].type, pItems[0].count );
payloadSize = CA_MESSAGE_ALIGN ( payloadSize );
dblPayloadSize = dbr_size [ DBR_DOUBLE ];
dblPayloadSize = CA_MESSAGE_ALIGN ( dblPayloadSize );
if ( payloadSize > dblPayloadSize ) {
unsigned factor = payloadSize / dblPayloadSize;
while ( factor ) {
if ( iterations > 10 * factor ) {
iterations /= factor;
break;
}
factor /= 2;
}
}
printf ( "\t### async put test ###\n");
nBytesSent = sizeof ( caHdr ) + CA_MESSAGE_ALIGN( payloadSize );
nBytesRecv = 0u;
timeIt ( test_put, pItems, iterations,
nBytesSent * iterations,
nBytesRecv * iterations );
printf ( "\t### async get test ###\n");
nBytesSent = sizeof ( caHdr );
nBytesRecv = sizeof ( caHdr ) + CA_MESSAGE_ALIGN ( payloadSize );
timeIt ( test_get, pItems, iterations,
nBytesSent * ( iterations ),
nBytesRecv * ( iterations ) );
printf ("\t### synch get test ###\n");
nBytesSent = sizeof ( caHdr );
nBytesRecv = sizeof ( caHdr ) + CA_MESSAGE_ALIGN ( payloadSize );
if ( iterations > 100 ) {
iterations /= 100;
}
else if ( iterations > 10 ) {
iterations /= 10;
}
timeIt ( test_wait, pItems, iterations,
nBytesSent * iterations,
nBytesRecv * iterations );
}
/*
* catime ()
*/
int catime ( const char * channelName,
unsigned channelCount, enum appendNumberFlag appNF )
{
unsigned i;
int j;
unsigned strsize;
unsigned nBytesSent, nBytesRecv;
ti *pItemList;
if ( channelCount == 0 ) {
printf ( "channel count was zero\n" );
return 0;
}
pItemList = calloc ( channelCount, sizeof (ti) );
if ( ! pItemList ) {
return -1;
}
SEVCHK ( ca_context_create ( ca_disable_preemptive_callback ),
"Unable to initialize" );
if ( appNF == appendNumber ) {
printf ( "Testing with %u channels named %snnn\n",
channelCount, channelName );
}
else {
printf ( "Testing with %u channels named %s\n",
channelCount, channelName );
}
strsize = sizeof ( pItemList[0].name ) - 1;
nBytesSent = 0;
nBytesRecv = 0;
for ( i=0; i < channelCount; i++ ) {
if ( appNF == appendNumber ) {
sprintf ( pItemList[i].name,"%.*s%.6u",
(int) (strsize - 15u), channelName, i );
}
else {
strncpy ( pItemList[i].name, channelName, strsize);
}
pItemList[i].name[strsize]= '\0';
pItemList[i].count = 0;
pItemList[i].pValue = 0;
nBytesSent += 2 * ( CA_MESSAGE_ALIGN ( strlen ( pItemList[i].name ) )
+ sizeof (caHdr) );
nBytesRecv += 2 * sizeof (caHdr);
}
printf ( "Channel Connect Test\n" );
printf ( "--------------------\n" );
timeIt ( test_search, pItemList, channelCount, nBytesSent, nBytesRecv );
printSearchStat ( pItemList, channelCount );
for ( i = 0; i < channelCount; i++ ) {
size_t count = ca_element_count ( pItemList[i].chix );
size_t size = sizeof ( dbr_string_t ) * count;
pItemList[i].count = count;
pItemList[i].pValue = malloc ( size );
assert ( pItemList[i].pValue );
}
printf (
"channel name=%s, native type=%d, native count=%u\n",
ca_name (pItemList[0].chix),
ca_field_type (pItemList[0].chix),
pItemList[0].count );
printf ("Pend Event Test\n");
printf ( "----------------\n" );
timeIt ( test_pend, NULL, 100, 0, 0 );
for ( i = 0; i < channelCount; i++ ) {
dbr_float_t * pFltVal = ( dbr_float_t * ) pItemList[i].pValue;
double val = i;
val /= channelCount;
for ( j = 0; j < pItemList[i].count; j++ ) {
pFltVal[j] = (dbr_float_t) val;
}
pItemList[i].type = DBR_FLOAT;
}
printf ( "DBR_FLOAT Test\n" );
printf ( "--------------\n" );
test ( pItemList, channelCount );
for ( i = 0; i < channelCount; i++ ) {
dbr_double_t * pDblVal = ( dbr_double_t * ) pItemList[i].pValue;
double val = i;
val /= channelCount;
for ( j = 0; j < pItemList[i].count; j++ ) {
pDblVal[j] = (dbr_double_t) val;
}
pItemList[i].type = DBR_DOUBLE;
}
printf ( "DBR_DOUBLE Test\n" );
printf ( "---------------\n" );
test ( pItemList, channelCount );
for ( i = 0; i < channelCount; i++ ) {
dbr_string_t * pStrVal = ( dbr_string_t * ) pItemList[i].pValue;
double val = i;
val /= channelCount;
for ( j = 0; j < pItemList[i].count; j++ ) {
sprintf ( pStrVal[j], "%f", val );
}
pItemList[i].type = DBR_STRING;
}
printf ( "DBR_STRING Test\n" );
printf ( "---------------\n" );
test ( pItemList, channelCount );
for ( i = 0; i < channelCount; i++ ) {
dbr_int_t * pIntVal = ( dbr_int_t * ) pItemList[i].pValue;
double val = i;
val /= channelCount;
for ( j = 0; j < pItemList[i].count; j++ ) {
pIntVal[j] = (dbr_int_t) val;
}
pItemList[i].type = DBR_INT;
}
printf ( "DBR_INT Test\n" );
printf ( "------------\n" );
test ( pItemList, channelCount );
printf ( "Get Latency Test\n" );
printf ( "----------------\n" );
for ( i = 0; i < channelCount; i++ ) {
dbr_double_t * pDblVal = ( dbr_double_t * ) pItemList[i].pValue;
for ( j = 0; j < pItemList[i].count; j++ ) {
pDblVal[j] = 0;
}
pItemList[i].type = DBR_DOUBLE;
}
measure_get_latency ( pItemList, channelCount );
printf ( "Free Channel Test\n" );
printf ( "-----------------\n" );
timeIt ( test_free, pItemList, channelCount, 0, 0 );
SEVCHK ( ca_task_exit (), "Unable to free resources at exit" );
for ( i = 0; i < channelCount; i++ ) {
free ( pItemList[i].pValue );
}
free ( pItemList );
return CATIME_OK;
}

Some files were not shown because too many files have changed in this diff Show More