Compare commits

...

357 Commits

Author SHA1 Message Date
Andrew Johnson
7aefee6737 Set Base version number for 3.16.1-rc1 2017-05-09 14:00:29 -05:00
Andrew Johnson
f9564a3b82 Various Release Notes tweaks 2017-05-09 13:57:17 -05:00
Andrew Johnson
17da4bfc1f Additional ReleaseChecklist updates 2017-05-09 13:08:59 -05:00
Ralph Lange
2fe8d82872 ci: make appveyor version number unambiguous 2017-05-09 14:03:40 +02:00
Ralph Lange
2ff9f249a0 ci: add appveyor configuration 2017-05-09 12:01:36 +02:00
Andrew Johnson
5ec1340902 Convert ReleaseChecklist commands to git 2017-05-08 20:45:39 -05:00
Michael Davidsaver
269f828733 ca: assume that CA name servers have minor version >=12
Assume that servers listed in EPICS_CA_NAME_SERVERS
support CA >=12, practically >=1 to support the
authentication messages.
2017-05-07 20:27:34 -04:00
Michael Davidsaver
4ce60c9797 src/tools: avoid dep. warning in rRDD generated
when building a support module
2017-05-07 20:27:34 -04:00
Michael Davidsaver
d5fc8c9b76 ioc/dbStatic: reduce warning spam for typed rset
There are an amazing number of warnings in any code which
includes recSup.h indirectly, including dbStaticLib.h.
Don't use the RECSUPFUN typedef internally to reduce
the number.
2017-05-07 10:06:38 -04:00
Andrew Johnson
93c0dcd3e5 Missing include 2017-05-06 01:11:53 -05:00
Andrew Johnson
fd583ac594 Fix MSC 2-digit-exponent in cvtFastTest.c 2017-05-06 00:41:52 -05:00
Michael Davidsaver
9621ff1552 libCom/test: cvtFastTest improve output 2017-05-05 20:54:19 -04:00
Michael Davidsaver
3f49787be1 ioc/db/test: fix jlinkz dllimport/export 2017-05-05 20:38:20 -04:00
Michael Davidsaver
bbd9ba0b6d std/filters: fix filters test harness 2017-05-05 20:15:03 -04:00
Michael Davidsaver
fcd443a026 missing test spec 2017-05-05 17:14:15 -04:00
Michael Davidsaver
02809de380 fix long long constants 2017-05-04 21:13:07 -04:00
Michael Davidsaver
987943be4e Merge remote-tracking branch 'int64b/master'
* int64b/master: (25 commits)
  std/rec: streamline variable names in int64in/int64out
  std/rec/test: recMiscTest check in64in/out
  ioc/db: dbUnitTest helps support int64
  std/rec: ioc64in/outRecord typed rset
  minor
  std/rec: fix copyright in int64in sources
  std: remove SCM keywords from int64in and int64out sources
  std/rec: fix promptgroups in dbd.pod files
  std/rec: add and improve pod for int64in and int64out
  std/rec: add pod documentation content for int64out
  std/rec: add pod documentation for int64out record
  dbStatic: dbPutStringNum() overflow handling
  dbStatic: more informative error for bad field value
  dbStatic: dbPutStringNum(, "") not an error
  Release Notes
  cvtFastPerform: Rename reserved member names, fix for vxWorks
  Simplify epicsConvertDoubleToFloat()
  More cvtFastPerform changes
  Collate and report by precision
  Restructure cvtFastPerform, fix VxWorks build
  ...
2017-05-04 20:18:24 -04:00
Michael Davidsaver
16a3657613 Merge remote-tracking branch 'linksup/master'
* linksup/master: (112 commits)
  ioc/dbStatic: rename link debugging info tags
  jlif future proof for 64-bit json parser
  Demonstrate and use numeric literals in calc args
  separate jlink and lset debug flags
  std/link: runtime conditional debugging in calc/const
  std/rec/test: extend linkRetargetLink w/ jlink
  ioc/db: dbUnitTest add testdbPutArrFieldOk()
  ioc/db: cleanup dbEvent freeLists
  ioc/db: dbUnitTest testMonitor leaks dbChannel
  std/link: all calc example
  jlink conditional debug print
  ioc/as: dbCore needs ca
  Additional linkInitTest checks
  Minimize work done in readLocked routine
  Minimize work done in readLocked() routine
  Cosmetic changes to various soft device supports
  Enhancements to subArray record & soft device support
  Fix bug in eventRecord::init_record
  Updates to Release Notes and links.html
  Make dbLinkIs{Constant|Volatile}() return only true/false
  ...

Conflicts:
	documentation/RELEASE_NOTES.html
	src/ioc/db/dbAccess.c
2017-05-04 20:14:30 -04:00
Michael Davidsaver
8ae7930375 ioc/dbStatic: rename link debugging info tags 2017-05-04 20:12:02 -04:00
Andrew Johnson
05d3e640cd Testing msi: Add retries if necessary
Hoping this will fix the annoying problems on Windows Jenkins.
2017-05-04 14:48:18 -05:00
Andrew Johnson
efe8d69f82 dbStaticTest: More friendly test output 2017-05-04 12:33:32 -05:00
Andrew Johnson
2c65739286 Change indfield settings in new dbInitEntryFrom*()
Can get indfield value from dbAddr->pflddes->indRecordType.
Make FromRecord set indfield=0 like dbFindRecord() does.

Adjust dbStaticTest to match.
2017-05-04 12:31:17 -05:00
Andrew Johnson
93fe387e87 Fix dbStaticTest recnode flags check 2017-05-04 12:23:57 -05:00
Ralph Lange
ad0695b119 std/rec: streamline variable names in int64in/int64out 2017-05-04 09:27:23 +02:00
Michael Davidsaver
8f880a614c ioc/db/test: check record node flags 2017-05-03 19:32:50 -04:00
Michael Davidsaver
7805fbe295 ioc/dbStatic: rename dbRecordNode aliasedRecord -> aliasedRecnode 2017-05-03 19:31:38 -04:00
Michael Davidsaver
2a81e0b338 std/rec/test: recMiscTest check in64in/out 2017-05-03 19:18:52 -04:00
Michael Davidsaver
5e0dc5d1c9 ioc/db: dbUnitTest helps support int64 2017-05-03 18:39:43 -04:00
Michael Davidsaver
1b16c7130b std/rec: ioc64in/outRecord typed rset 2017-05-03 17:58:29 -04:00
Michael Davidsaver
925d03bcec minor 2017-05-03 17:54:58 -04:00
Michael Davidsaver
1151d78cb5 Merge remote-tracking branch 'launchpad/master'
* launchpad/master: (116 commits)
  ioc/rsrv: bounds check DBR
  CAref mention EPICS_CA_MCAST_TTL
  EPICS_CA_AUTO_MAX_ARRAY_BYTES -> EPICS_CA_AUTO_ARRAY_BYTES
  missing include
  ioc/db/test: dbStaticTest dbInitEntryFromAddr() works before iocInit()
  ioc/db/test: dbStaticTest test operations on aliases
  ioc: rename dbCommonPvt::recnode
  ioc/dbStatic: better alias tracking
  ioc/dbStatic: add dbInitEntryFromRecord()
  ioc: populate RDES early
  rename dbInitEntryFromChannel -> dbInitEntryFromAddr
  ioc/db: Add dbCommonPvt
  ioc/dbStatic: add dbInitEntryFromChannel()
  ioc/dbStatic: dbAllocRecord whitespace
  ioc/rsrv: fix C89 issue
  add EPICS_CA_MCAST_TTL
  update RELEASE_NOTES
  replace caLimitArray with EPICS_CA_AUTO_MAX_ARRAY_BYTES
  update RELEASE_NOTES
  rename iocshFind -> iocshFindCommand
  ...

Conflicts:
	documentation/RELEASE_NOTES.html
	src/ioc/db/dbConvert.c
	src/ioc/db/dbFastLinkConv.c
	src/ioc/db/test/Makefile
	src/ioc/db/test/dbPutGetTest.c
	src/ioc/db/test/dbPutGetTest.db
	src/ioc/dbStatic/dbStaticRun.c
2017-05-03 17:54:43 -04:00
Michael Davidsaver
b4c625d8d1 jlif future proof for 64-bit json parser 2017-05-03 17:27:57 -04:00
Michael Davidsaver
096fb5e0a2 Merge remote-tracking branch 'addr2entry/master'
* addr2entry/master:
  ioc/db/test: dbStaticTest dbInitEntryFromAddr() works before iocInit()
  ioc/db/test: dbStaticTest test operations on aliases
  ioc: rename dbCommonPvt::recnode
  ioc/dbStatic: better alias tracking
  ioc/dbStatic: add dbInitEntryFromRecord()
  ioc: populate RDES early
  rename dbInitEntryFromChannel -> dbInitEntryFromAddr
  ioc/db: Add dbCommonPvt
  ioc/dbStatic: add dbInitEntryFromChannel()
  ioc/dbStatic: dbAllocRecord whitespace
2017-05-03 17:07:07 -04:00
Michael Davidsaver
8640e1c9fb Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  ioc/rsrv: bounds check DBR
2017-05-03 17:06:51 -04:00
Michael Davidsaver
a7c14ec995 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  ioc/rsrv: bounds check DBR
2017-05-03 16:53:43 -04:00
Michael Davidsaver
e430d097b7 ioc/rsrv: bounds check DBR
avoid array overrun when evaluating dbr_size_n() macro.
2017-05-03 16:49:28 -04:00
Michael Davidsaver
d154d8eab7 CAref mention EPICS_CA_MCAST_TTL 2017-05-03 14:17:56 -04:00
Michael Davidsaver
3fbdcdb032 EPICS_CA_AUTO_MAX_ARRAY_BYTES -> EPICS_CA_AUTO_ARRAY_BYTES 2017-05-03 13:59:35 -04:00
Ralph Lange
eedf296cd2 std/rec: fix copyright in int64in sources 2017-05-03 17:07:46 +02:00
Ralph Lange
f0d7d42ab4 std: remove SCM keywords from int64in and int64out sources 2017-05-03 17:07:06 +02:00
Ralph Lange
5761028d6f std/rec: fix promptgroups in dbd.pod files 2017-05-03 17:00:19 +02:00
Michael Davidsaver
fbc1ed26f0 missing include 2017-05-03 10:18:32 -04:00
Ralph Lange
93b47f103e std/rec: add and improve pod for int64in and int64out 2017-05-03 16:17:27 +02:00
Michael Davidsaver
1917d0563a ioc/db/test: dbStaticTest dbInitEntryFromAddr() works before iocInit() 2017-05-02 21:30:43 -04:00
Michael Davidsaver
da4bf2d5ee ioc/db/test: dbStaticTest test operations on aliases 2017-05-02 21:12:09 -04:00
Michael Davidsaver
ec3a89e43c ioc: rename dbCommonPvt::recnode 2017-05-02 21:11:46 -04:00
Michael Davidsaver
62475a383e ioc/dbStatic: better alias tracking
Ensure that alias of alias sets DBRN_FLAGS_HASALIAS
on the aliased dbRecordNode.

Add dbFollowAlias() for completeness.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
6ba949cdb4 ioc/dbStatic: add dbInitEntryFromRecord() 2017-05-02 21:11:46 -04:00
Michael Davidsaver
5d37bc2996 ioc: populate RDES early
The record type is known at allocation time,
so store RDES immediately.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
2eaede9925 rename dbInitEntryFromChannel -> dbInitEntryFromAddr 2017-05-02 21:11:46 -04:00
Michael Davidsaver
12d68e6021 ioc/db: Add dbCommonPvt
Add some hidden "fields" for every record.
Allows Base internal hidden accounting
which can be changed without an ABI break.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
78a7ad168e ioc/dbStatic: add dbInitEntryFromChannel()
Constant time population of a DBENTRY from
a valid dbAddr.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
f716b1b26a ioc/dbStatic: dbAllocRecord whitespace 2017-05-02 21:11:46 -04:00
Michael Davidsaver
0bbb381efd ioc/rsrv: fix C89 issue 2017-05-02 21:06:35 -04:00
Michael Davidsaver
f2a1834dc9 add EPICS_CA_MCAST_TTL
may be necessary/helpful for mcast search/beacon usage
across sub-nets.
2017-05-02 20:35:00 -04:00
Michael Davidsaver
6572816a6a update RELEASE_NOTES 2017-05-02 20:16:49 -04:00
Michael Davidsaver
c304e29da6 Merge remote-tracking branch 'cahuge/master'
* cahuge/master:
  replace caLimitArray with EPICS_CA_AUTO_MAX_ARRAY_BYTES
  ca: fix export caLimitArray on win32
  rsrv: export variable caLimitArray
  rsrv: optional max_array_bytes
  cas: simplify buffer alloc
  ca: large array free list is optional
  rsrv: support larger than max. array bytes
  pcas: support larger than max array bytes
  ca: support alloc larger than max array bytes
2017-05-02 20:06:54 -04:00
Michael Davidsaver
9fd8eec2e2 replace caLimitArray with EPICS_CA_AUTO_MAX_ARRAY_BYTES 2017-05-02 19:31:21 -04:00
Michael Davidsaver
a873c4f3dc Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  rename iocshFind -> iocshFindCommand
  Added patch
  Changed function outputs to remove pointer to next function.
  more whitespace
  whitespace
  Added functions to allow access to what functions and variables the ioc shell has registered.
  missing include
  ioc/dbStatic: dbFreeBase() don't double free alias'd records
  ioc/dbStatic: plug leak in dbFreeBase()
  ioc/dbStatic: whitespace
  Fix indentation warning from GCC
  libCom/test: errlog test more verbose
  libCom: STATIC_ASSERT use c++11 static_assert when possible
  Check for empty PV names in Perl catools

Conflicts:
	src/std/rec/subRecord.c
2017-05-02 19:08:51 -04:00
Michael Davidsaver
26650d6cbf update RELEASE_NOTES 2017-05-02 19:02:18 -04:00
Michael Davidsaver
d1a0b74c83 Merge remote-tracking branch 'camodern/master'
* camodern/master:
  cas: ignore CA client version older than v4.4
  rsrv: remove !CA_V44() code
  rsrv: no ca exception response to UDP
  rsrv: ignore CA client version older than v4.4
  cas: honor DOREPLY for TCP searches
  cas: ignore echo and unexpected UDP
  rsrv: send channel create failure
  rsrv: UDP search ignore DOREPLY
  rsrv: ignore echo and unexpected UDP

Conflicts:
	src/ca/legacy/pcas/generic/casDGClient.cc
2017-05-02 18:41:09 -04:00
Michael Davidsaver
875e4db3f9 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  missing include

Conflicts:
	src/ioc/dbStatic/dbStaticLib.c
2017-05-02 18:38:40 -04:00
Michael Davidsaver
8c8604c503 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  ioc/dbStatic: dbFreeBase() don't double free alias'd records
  ioc/dbStatic: plug leak in dbFreeBase()
  ioc/dbStatic: whitespace
  Fix indentation warning from GCC
  libCom/test: errlog test more verbose
  libCom: STATIC_ASSERT use c++11 static_assert when possible
  Check for empty PV names in Perl catools

Conflicts:
	src/ioc/dbStatic/dbStaticLib.c
	src/libCom/osi/epicsAssert.h
2017-05-02 18:31:40 -04:00
Michael Davidsaver
9d7c4434ad rename iocshFind -> iocshFindCommand 2017-05-02 18:23:52 -04:00
Keenan Lang
67e12bca9f Added patch 2017-05-02 18:23:52 -04:00
Keenan Lang
15cb72acbc Changed function outputs to remove pointer to next function. 2017-05-02 18:23:52 -04:00
Keenan Lang
45ed461665 more whitespace 2017-05-02 18:23:52 -04:00
Keenan Lang
3986e43135 whitespace 2017-05-02 18:23:51 -04:00
Keenan Lang
daad3c6995 Added functions to allow access to what functions and variables the ioc shell has registered. 2017-05-02 18:23:51 -04:00
Michael Davidsaver
38be82a154 missing include 2017-05-02 18:22:57 -04:00
Michael Davidsaver
27cd9fd051 ioc/dbStatic: dbFreeBase() don't double free alias'd records
dbFreeBase() has been broken since alias() was introduced.

Traversal of recList in the function assumed that dbDeleteRecord()
remove only the current dbRecordNode.  However, dbDeleteRecord()
called dbDeleteAliases() which removes alias dbRecordNode s.
If this happens (as it often does) to be the node immediately
after the real node, dbFreeBase() will then iterate using
a ellDelete()d node.
2017-05-02 18:04:06 -04:00
Michael Davidsaver
1ffce72a38 ioc/dbStatic: plug leak in dbFreeBase() 2017-05-02 18:02:05 -04:00
Michael Davidsaver
dcac64d50f ioc/dbStatic: whitespace 2017-05-02 18:01:39 -04:00
Andrew Johnson
83428d2b2c db/test: Cleanup unused variable 2017-05-02 12:39:09 -05:00
Ralph Lange
1235ad76e7 std/rec: add pod documentation content for int64out 2017-05-02 13:51:44 +02:00
Andrew Johnson
1cad1c5ba6 Demonstrate and use numeric literals in calc args 2017-04-29 20:43:54 -05:00
Michael Davidsaver
12fc7ed07c libCom: add EPICS_FUNCTION
Automatic macro which expands to the current function name.
Useful in debug prints.
2017-04-28 19:19:14 -04:00
Michael Davidsaver
564ef01951 typo 2017-04-28 19:19:14 -04:00
Michael Davidsaver
f65b2119ad separate jlink and lset debug flags
"lsetDebug" for lset callbacks and "jlinkDebug" for jlink parsing.
2017-04-28 17:11:47 -04:00
Michael Davidsaver
4a9fe82575 std/link: runtime conditional debugging in calc/const 2017-04-28 16:59:26 -04:00
Michael Davidsaver
2a1f790909 std/rec/test: extend linkRetargetLink w/ jlink 2017-04-28 16:59:26 -04:00
Michael Davidsaver
d752b962d5 ioc/db: dbUnitTest add testdbPutArrFieldOk() 2017-04-28 16:44:18 -04:00
Andrew Johnson
0bf789db4c Fix indentation warning from GCC 2017-04-28 14:56:18 -05:00
Michael Davidsaver
b4db176e48 ioc/db: cleanup dbEvent freeLists 2017-04-28 15:47:27 -04:00
Michael Davidsaver
d397f0fd92 ioc/db: dbUnitTest testMonitor leaks dbChannel 2017-04-28 15:43:17 -04:00
Ralph Lange
b096dc3e01 std/rec: add pod documentation for int64out record 2017-04-28 16:41:02 +02:00
Michael Davidsaver
be8de34130 std/link: all calc example 2017-04-27 19:50:46 -04:00
Michael Davidsaver
579a0791ea jlink conditional debug print
Enable magic info("linkDebug","YES") to enable
debug prints during parsing.
2017-04-27 19:46:33 -04:00
Michael Davidsaver
e51cc39b0c ioc/as: dbCore needs ca 2017-04-27 17:24:23 -04:00
Michael Davidsaver
e296e99667 Merge remote-tracking branch 'launchpad/master'
* launchpad/master:
  libCom: dbmfMalloc cantProeed() on failure
  ioc/db/test: dbCaLinkTest fix sync
  oops
  std/filter/test: use dbUnitTest
  travis-ci enable mingw w/ dll
  travisci
  catools: Fix SEGFAULT from bad PV names
  typo
  Fix for dbCa warning seg-fault
  Fix postfix.h macro arg, document
  libCom/test: epicsCalcTest use exact postifx buffers

Conflicts:
	src/ioc/db/test/dbCaLinkTest.c
2017-04-27 17:17:29 -04:00
Michael Davidsaver
57cbe61709 libCom/test: errlog test more verbose 2017-04-27 16:53:40 -04:00
Michael Davidsaver
a2ab17a782 libCom: STATIC_ASSERT use c++11 static_assert when possible 2017-04-27 16:52:33 -04:00
Michael Davidsaver
8677c84528 libCom: dbmfMalloc cantProeed() on failure
most calling code doesn't check for NULL.
2017-04-27 15:30:35 -04:00
Michael Davidsaver
052573f4ca ioc/db/test: dbCaLinkTest fix sync 2017-04-27 15:14:58 -04:00
Michael Davidsaver
7a727bbd41 Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  oops
  std/filter/test: use dbUnitTest
  travis-ci enable mingw w/ dll
  travisci
  catools: Fix SEGFAULT from bad PV names
  typo
  Fix for dbCa warning seg-fault
  Fix postfix.h macro arg, document
  libCom/test: epicsCalcTest use exact postifx buffers
2017-04-27 14:31:53 -04:00
Michael Davidsaver
c6910decfc oops 2017-04-27 14:19:15 -04:00
Michael Davidsaver
b01dd38526 std/filter/test: use dbUnitTest 2017-04-27 14:09:41 -04:00
Andrew Johnson
d825f87359 Check for empty PV names in Perl catools 2017-04-27 12:10:27 -05:00
Michael Davidsaver
82ff67a204 travis-ci enable mingw w/ dll 2017-04-27 12:57:01 -04:00
Michael Davidsaver
e751480b06 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  travisci
  catools: Fix SEGFAULT from bad PV names
  typo
2017-04-27 12:55:35 -04:00
Michael Davidsaver
3184371e8d travisci 2017-04-27 12:53:35 -04:00
Andrew Johnson
f2e54be965 catools: Fix SEGFAULT from bad PV names 2017-04-27 10:52:07 -05:00
Andrew Johnson
0748adfb9a Additional linkInitTest checks
Now tests array record types and the eventRecord.
Also moved repeated IOC startup code into separate function.
2017-04-26 16:04:13 -05:00
Andrew Johnson
4813b37538 Minimize work done in readLocked routine
Move post-I/O back to read_event.
Fix initialization bug.
2017-04-26 16:01:09 -05:00
Andrew Johnson
bbd94928bb Minimize work done in readLocked() routine
Move post-I/O work back to the read_xx routines.
2017-04-26 15:59:03 -05:00
Andrew Johnson
c13a4f24ce Cosmetic changes to various soft device supports 2017-04-26 15:55:03 -05:00
Andrew Johnson
d1af663705 Enhancements to subArray record & soft device support
Permit record's use as a look-up-table by reading constant
input array data in dset::read_sa() routine.

Move sub-array operation into a separate function.
Extract subarray from constant INP value at device init.
Reduce the work done inside readLocked() to a minimum.
Limit NELM value to at most MALM in record init routine.
2017-04-26 15:52:08 -05:00
Andrew Johnson
4eafb6fd8e Fix bug in eventRecord::init_record
Look up event handle /after/ the device init routine has been run,
in case it modified the event name in VAL. That didn't used to
be possible because constant links couldn't return strings.
2017-04-26 15:03:43 -05:00
Andrew Johnson
33f3145fcc Updates to Release Notes and links.html 2017-04-25 22:52:08 -05:00
Andrew Johnson
c71afb631c Make dbLinkIs{Constant|Volatile}() return only true/false 2017-04-25 20:37:09 -05:00
Jeong Han Lee
c22670cbb0 typo 2017-04-24 21:06:30 -04:00
Andrew Johnson
35385bc688 Merge changes from 3.14 into 3.15
Changes to be committed:
	modified:   src/ioc/db/dbCa.c
	modified:   src/libCom/calc/postfix.h
	modified:   src/libCom/test/epicsCalcTest.cpp
2017-04-24 18:10:53 -05:00
Andrew Johnson
c5decfbd12 Fix for dbCa warning seg-fault
Don't queue an errlog message containing a pointer to a string
that will disappear soon.

Thanks to Matt Pearson for the bug analysis.
2017-04-24 18:03:53 -05:00
Andrew Johnson
da94b7a2e4 Fix dbConstLink to handle a long-string array properly
Added a new parser dbLSConvertJSON for long-string arrays.
New test checks that only the first string element is used.
2017-04-24 17:09:01 -05:00
Andrew Johnson
311ad57e93 printfRecord: Handle const long-strings in "%ls"
Adds some tests for printfRecord.
2017-04-24 15:18:52 -05:00
Andrew Johnson
30e634b97b Adjust calcout's handling of undefined links 2017-04-23 23:32:15 -05:00
Andrew Johnson
421a2c8eb9 Tidy up lnkConst.c after Michael's bug-fix changes
Should make the code easier to follow.
2017-04-23 00:11:22 -05:00
Michael Davidsaver
cfe9a51c5d std/rec/test: start linkInitTest 2017-04-21 17:26:58 -04:00
Michael Davidsaver
066984e11d Merge branch 'master' into link
* master: (226 commits)
  ioc/db: testdbGetFieldEqual() detect zero size
  Cleanup in asLib
  Allow whitespace before comments in AS config files
  Supress MS warning C4251
  Add a plan to std/filters/test/syncTest.c
  Fix dbUnitTest.c
  avoid void* +=
  Fix and test for macLib losing error status
  update notes
  libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible
  libCom/test: add ipAddrToAsciiTest to testHarness
  db/test: dbPutGetTest check dbGet() of long string field
  db: dbGet() ensure long string nil and actual string length
  db/test: dbPutGetTest check for dbGet() attribute crash
  db: fix dbGet() for attributes as long string
  db/test: dbPutGetTest add test for lp:1678494
  db: fix dbGet() of link fields as DBF_CHAR
  dbUnitTest: add testdbGetArrFieldEqual()
  db/test: add dbPutGetTest
  Update release notes as per Michael's review comment
  ...

Conflicts:
	src/ioc/db/dbLink.c
	src/ioc/db/test/Makefile
	src/std/dev/devSoSoftCallback.c
	src/std/rec/boRecord.c
	src/std/rec/dfanoutRecord.c
	src/std/rec/longinRecord.c
	src/std/rec/longoutRecord.c
2017-04-21 17:20:12 -04:00
Andrew Johnson
e25a2964bc Fix postfix.h macro arg, document 2017-04-21 16:09:36 -05:00
Michael Davidsaver
6c062981fb Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  ioc/db: testdbGetFieldEqual() detect zero size
  Cleanup in asLib
  Allow whitespace before comments in AS config files
  Supress MS warning C4251
  Add a plan to std/filters/test/syncTest.c
  Fix dbUnitTest.c
  avoid void* +=
  Fix and test for macLib losing error status
  update notes
  libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible
  libCom/test: add ipAddrToAsciiTest to testHarness
  Adjusted .gitignore patterns
  libCom/test: add network libraries for Windows builds
  Moved .bzrignore to .gitignore
  libCom/test: add ipAddrToAsciiTest
  libCom: revise ipAddrToAscii
2017-04-21 16:16:03 -04:00
Michael Davidsaver
22b10adf29 ioc/db: testdbGetFieldEqual() detect zero size 2017-04-21 16:14:43 -04:00
Michael Davidsaver
8382367495 libCom/test: epicsCalcTest use exact postifx buffers
exposes INFIX_TO_POSTFIX_SIZE() bug
2017-04-21 16:13:18 -04:00
Michael Davidsaver
54e94a1e12 std/link: lnkConst refactor
Avoid variable with same name as typedef.
Confuses qtcreator.
2017-04-21 16:08:48 -04:00
Michael Davidsaver
414e5b82b8 std/link: lnkCalc require expression
error if 'expr' key isn't provided.
2017-04-21 16:08:33 -04:00
Michael Davidsaver
b99a7b9252 std/link: lnkConst fix mem leak and hard fail on no mem 2017-04-21 16:08:15 -04:00
Michael Davidsaver
43f6a06bcd std/link: lnkConst avoid cantProceed() 2017-04-21 16:08:10 -04:00
Michael Davidsaver
7121b016d5 ioc/db: dbConstLoadLS handle size=0
handle size=0 and clarify
2017-04-21 16:08:04 -04:00
Michael Davidsaver
8b24383e9e arrayOpTest: check initial dbGet value 2017-04-21 16:07:55 -04:00
Andrew Johnson
e99fe61e07 Fix postfix.h macro arg and document 2017-04-21 14:18:05 -05:00
Andrew Johnson
23cef0339e Fix buffer allocation bug in lnkCalc.c 2017-04-21 13:56:49 -05:00
Andrew Johnson
611cb3f52e Fix typos, remove FIXMEs from lnkConst.c 2017-04-21 13:55:59 -05:00
Andrew Johnson
7e60faae10 No need to truncate const string array elements 2017-04-21 13:04:53 -05:00
Andrew Johnson
821fb1302b Merged changes from 3.14 branch into 3.15 2017-04-20 16:57:08 -05:00
Andrew Johnson
64c16c0f6e Cleanup in asLib
Improve error messages.
Remove unnecessary pointer casts.
2017-04-20 16:27:20 -05:00
Andrew Johnson
9f01c47542 Allow whitespace before comments in AS config files
Fixes lp: #1677302
Makes the lexer patterns more like dbStatic.
Handle non-printable invalid characters in input properly.
2017-04-20 16:23:36 -05:00
Andrew Johnson
aca7b44a05 Supress MS warning C4251 2017-04-20 11:42:52 -05:00
Michael Davidsaver
4f1b244589 ca: fix export caLimitArray on win32 2017-04-20 09:54:05 -04:00
Andrew Johnson
dcb1f75b4d Cosmetic cleanups 2017-04-19 16:53:12 -05:00
Andrew Johnson
89f13aa51b Modify soft devices to synchronize TSEL=-2 timestamps
Use dbLinkDoLocked() to ensure a timestamp set by TSEL=-2
comes from the same update as the value.
2017-04-19 16:50:38 -05:00
Andrew Johnson
d2db634ed2 Add dbLinkDoLocked() support
New lset method, implemented in all link types.
Includes a test for the dbCa implementation.
2017-04-19 16:44:11 -05:00
Andrew Johnson
b8f542fc0d Add a plan to std/filters/test/syncTest.c 2017-04-18 14:49:40 -05:00
Andrew Johnson
6f9905d060 Fix dbUnitTest.c 2017-04-18 14:48:54 -05:00
Michael Davidsaver
f3841c4767 avoid void* += 2017-04-17 18:58:19 -04:00
Andrew Johnson
4f8fd545fa Merge branch 'fix-async-dns/master' into 3.14 2017-04-17 15:52:10 -05:00
Andrew Johnson
d4552af39b Fix and test for macLib losing error status
Problem found & diagnosed by Mark Rivers.
2017-04-17 11:47:21 -05:00
Michael Davidsaver
0c02c5cb30 update notes 2017-04-15 19:38:56 -04:00
Michael Davidsaver
1f90e98491 libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible 2017-04-15 19:34:04 -04:00
Michael Davidsaver
352fd32c45 libCom/test: add ipAddrToAsciiTest to testHarness 2017-04-12 20:30:23 -04:00
Michael Davidsaver
6bf66d1c93 Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  db/test: dbPutGetTest check dbGet() of long string field
  db: dbGet() ensure long string nil and actual string length
  db/test: dbPutGetTest check for dbGet() attribute crash
  db: fix dbGet() for attributes as long string
  db/test: dbPutGetTest add test for lp:1678494
  db: fix dbGet() of link fields as DBF_CHAR
  dbUnitTest: add testdbGetArrFieldEqual()
  db/test: add dbPutGetTest
  Adjusted .gitignore patterns
  Move .bzrignore to .gitignore
2017-04-06 20:32:48 -04:00
Michael Davidsaver
b624222a0f db/test: dbPutGetTest check dbGet() of long string field 2017-04-06 20:28:04 -04:00
Michael Davidsaver
739a112bec db: dbGet() ensure long string nil and actual string length 2017-04-06 20:28:01 -04:00
Michael Davidsaver
5e082bb75d db/test: dbPutGetTest check for dbGet() attribute crash 2017-04-06 20:27:37 -04:00
Michael Davidsaver
8ebfd0821a db: fix dbGet() for attributes as long string
dbGet() of "rec.RTYP$" with DBF_CHAR and nRequest==1
not handled correctly.  Results in crash.
2017-04-06 20:27:34 -04:00
Michael Davidsaver
fc8d4c2b5f db/test: dbPutGetTest add test for lp:1678494 2017-04-06 20:27:18 -04:00
Michael Davidsaver
1888253093 db: fix dbGet() of link fields as DBF_CHAR
dbGet() DBF_CHAR with nRequest==1 not handled correctly.
Results in crash.
2017-04-06 20:27:13 -04:00
Michael Davidsaver
8edefb9d63 dbUnitTest: add testdbGetArrFieldEqual() 2017-04-06 20:27:03 -04:00
Michael Davidsaver
0f31e35b87 db/test: add dbPutGetTest 2017-04-06 20:25:55 -04:00
Ralph Lange
865a870912 Merged typed-recsup branch (by Ben / Ralph) 2017-04-05 09:42:16 +02:00
Ralph Lange
9bfc8d8fad Update release notes as per Michael's review comment 2017-04-03 09:55:06 +02:00
Andrew Johnson
23a856ae9b Adjusted .gitignore patterns 2017-03-31 12:22:29 -05:00
Andrew Johnson
5a73ac59a1 Adjusted .gitignore patterns 2017-03-31 12:18:43 -05:00
Andrew Johnson
e0af3e2af5 Adjusted .gitignore patterns 2017-03-31 12:08:03 -05:00
Ralph Lange
5726ca6964 libCom/test: add network libraries for Windows builds 2017-03-31 15:01:51 +02:00
Ralph Lange
f164b14ba1 Moved .bzrignore to .gitignore 2017-03-30 15:43:15 -05:00
Ralph Lange
4c06cdc660 Move .bzrignore to .gitignore 2017-03-30 17:10:52 +02:00
Ralph Lange
6884e0ce61 Moved .bzrignore to .gitignore 2017-03-30 17:08:29 +02:00
Ralph Lange
9e778511ee Add opt-in switch to makeBaseApp example 2017-03-30 16:35:54 +02:00
Ralph Lange
bad1b0ead3 Update release notes with opt-in instructions 2017-03-30 16:26:54 +02:00
Ralph Lange
ecf5ab4a4c Deprecate RECSUPFUN and the untyped struct rset. 2017-03-30 16:14:09 +02:00
Ralph Lange
2f510af603 Use (typed) rset instead of (untyped) struct rset inside Base 2017-03-30 14:35:24 +02:00
Ralph Lange
0f2e26bc4c Make generated code always use typed_rset
always cast to cover old-style supports
2017-03-30 14:33:06 +02:00
Ralph Lange
26a4e1489f Make compilation inside Base USE_TYPED_RSET 2017-03-30 14:30:53 +02:00
Ralph Lange
19be96ec3a Add opt-in switch USE_TYPED_RSET 2017-03-30 14:28:48 +02:00
Ralph Lange
6397204354 Update release notes, C++ instructions are tested 2017-03-27 09:51:32 +02:00
Ralph Lange
89a858f655 Remove remaining REC_TYPE defines 2017-03-27 09:49:30 +02:00
Ralph Lange
0b410c1b03 Update release notes entry 2017-03-24 17:16:18 +01:00
Ralph Lange
4f8134c63c Fix xxxRecord in templates to make exampleApp work 2017-03-24 17:08:07 +01:00
Ralph Lange
ef2da59c24 Remove REC_TYPE and UNTYPED_RSET/oldRecSup.h; add casts to record types 2017-03-24 17:07:22 +01:00
Ben Franksen
40c9e4799b use new typed rset only if UNTYPED_RSET is not defined, adapted release notes
Also moved the old definition(s) to a separate header file named oldRecSup.h
to avoid cluttering the new header file.
2017-03-21 17:01:13 +01:00
Michael Davidsaver
675c2aff14 rsrv: export variable caLimitArray 2017-03-18 17:41:33 -04:00
Michael Davidsaver
1636f3d9fe rsrv: optional max_array_bytes
use of large array free list is optional
2017-03-18 17:41:33 -04:00
Michael Davidsaver
1e7c80c909 cas: simplify buffer alloc
eliminate casBufferFactory.
move small buffer free list into clientBufMemoryManager
2017-03-18 17:41:33 -04:00
Michael Davidsaver
2096c60652 ca: large array free list is optional 2017-03-18 17:41:33 -04:00
Michael Davidsaver
3009f88f64 rsrv: support larger than max. array bytes 2017-03-13 19:22:56 -04:00
Michael Davidsaver
b783427bf7 pcas: support larger than max array bytes
clientBufMemoryManager already supports allocations
larger than max array bytes, adjust callers inBuf/outBuf
to actually request larger allocations.
2017-03-13 19:22:53 -04:00
Michael Davidsaver
85b6b5c507 ca: support alloc larger than max array bytes
automatically try to allocate a custom buffer
when a message larger than ca max array bytes
is encountered.
2017-03-13 19:22:50 -04:00
Andrew Johnson
20627c0465 Merged changes from 3.15 branch to revno 12809 2017-03-08 10:36:41 -06:00
Andrew Johnson
f71102982f Fix "make -q" problems with shared library stubs 2017-03-06 18:46:46 -06:00
Andrew Johnson
d6b0c3041e Merged changes from 3.14 branch to revno 12703 2017-03-06 15:40:28 -06:00
Andrew Johnson
214e9534cc Allow 'make -q' to work with CHECK_RELEASE=NO 2017-03-03 18:18:57 -06:00
Andrew Johnson
17bd1ae6d0 db/test: Fix warning from clang 2017-03-03 12:23:36 -06:00
Ben Franksen
f71fe62bc3 added release notes entry 2017-03-03 17:40:24 +01:00
Ben Franksen
825c075df7 fixes in recSup and record types according to merge review
* removed struct valueDes
* made get_value take void (no arguments), added deprecation note
* removed misleading array size comment for get_units

Also added const to method parameters exactly where called in base with
const arguments.
2017-03-03 16:43:50 +01:00
Ben Franksen
ff91ede462 revert use of struct dbr_precision in call to get_precision in dbAccess.c 2017-03-03 16:41:03 +01:00
Michael Davidsaver
1d749ac7e7 dbLock: add assert in dbScanLock
catch locking attempts before iocInit()
2017-02-28 21:00:57 -06:00
Michael Davidsaver
6377c2e1e4 db/test: dbPutLinkTest include json links and more 2017-02-28 20:58:11 -06:00
Andrew Johnson
8069d9d80b dbUnitTest: Improve output slightly 2017-02-28 20:55:05 -06:00
Michael Davidsaver
46993a5e38 dbUnitTest: more informative dbPutField*() 2017-02-28 20:09:21 -06:00
Michael Davidsaver
2bb02e732a libCom: add errSymMsg() error message lookup
Like errSymLookup() but always returns a static string.
2017-02-28 20:06:42 -06:00
Michael Davidsaver
428dfe7a5c add testing lset 2017-02-28 18:00:51 -06:00
Andrew Johnson
5dcd3483ba dbStatic: dbPutStringNum() overflow handling
Default to accepting over-size integers in DB fields, truncate to field size.
E.g. permits setting DBF_LONG fields to 0xffffffff.
Adds dbConvertStrict config variable to disable this.
2017-02-28 00:25:43 -06:00
Michael Davidsaver
2a0cd00958 libca: lock when removing from msgMultiPVList 2017-02-27 14:48:30 -05:00
Michael Davidsaver
d744b06a28 libca: findOrCreateVirtCircuit() can return w/ piiu==NULL 2017-02-27 11:07:17 -05:00
Ben Franksen
1c3ffa1c76 fixed the wrong fix for getOptions in dbAccess.h 2017-02-26 13:54:58 +01:00
Michael Davidsaver
048b75304d libCom/test: add ipAddrToAsciiTest 2017-02-25 19:08:46 -05:00
Ben Franksen
aaafb1a5de db: call rset::get_precision with wrong type 2017-02-25 16:42:29 -05:00
Ben Franksen
cc946b760c partly fix lp:1666924, i.e. for rset only, as described in the ticket
This means:

* typed method definitions for struct rset
* using REC_TYPE macro in place of dbCommon
* define REC_TYPE as dbCommon unless defined
* in record supports, define REC_TYPE before including epics headers
* fix a few method types in record supports (e.g. void* -> REC_TYPE*)
* fix the type errors gcc finds in dbAccess.c and dbConvert.c
2017-02-24 21:11:11 +01:00
Michael Davidsaver
5783823e25 libCom: revise ipAddrToAscii
create multiple light-weight engines to
track transactions by engine and cancel
all transactions when an engine is released.

prior to fix for lp:1527636 this was ensured
for the last/only owner for the engine singleton.
2017-02-23 20:08:46 -05:00
Andrew Johnson
00549c832a Fix HTML entities 2017-02-17 14:16:57 -06:00
Andrew Johnson
c52088205e Remove constant link checks from test device 2017-02-17 14:15:31 -06:00
Andrew Johnson
e95fcb2e06 Merged changes from 3.15 branch, to revno 12807 2017-02-01 11:57:04 -06:00
Andrew Johnson
a7f0525ac7 Update Release Checklist 2017-01-30 18:04:47 -06:00
Andrew Johnson
de698f370a Merged Windows fixes from 3.14 branch, to revno 12699 2017-01-30 14:31:04 -06:00
Andrew Johnson
faf691a5be VS2015 starting to dislike '/' for compiler flags 2017-01-30 12:11:29 -06:00
Andrew Johnson
3a0e52fc3f Fix Windows dllPath.bat properly 2017-01-24 14:17:37 -06:00
Andrew Johnson
a105c6f538 Always quote Windows PATH arg's 2017-01-24 11:48:36 -06:00
Andrew Johnson
73eecbb759 Merged ARCH and bind fixes from 3.14 branch, revno 12696 2017-01-23 17:20:51 -06:00
Andrew Johnson
3e58c59377 Fix CA server bind issue from Freddie Akeroyd 2017-01-19 12:33:54 -06:00
Andrew Johnson
b9ae6c3308 Allow ARCH with trailing spaces 2017-01-18 10:59:36 -06:00
Andrew Johnson
3fd659e693 Merged PATH fix from 3.14 branch, revno 12694 2017-01-16 16:12:04 -06:00
Andrew Johnson
7310d78057 Prepend to PATH, not append 2017-01-16 10:46:56 -06:00
Andrew Johnson
051c059938 Removed some Revision-Id keywords 2017-01-06 17:31:51 -06:00
Andrew Johnson
dfc1b8ac23 Merged scan-rate protection changes from 3.14 branch, to revno 12693 2017-01-06 17:24:57 -06:00
Andrew Johnson
49e0e23f76 Better protection against bad periodic scan rates 2017-01-06 15:38:03 -06:00
Andrew Johnson
4a0fd0b954 Fix error message 2017-01-05 14:09:03 -06:00
Andrew Johnson
20dda339cc Make *_INC files order-only prerequisites 2017-01-04 16:32:13 -06:00
Andrew Johnson
7ec6be5d14 Update version numbers in documents for 3.15.6 2016-12-13 17:03:54 -06:00
Ralph Lange
eff44268e9 Set version to 3.15.5-DEV, close 3.15.5 chapter in release notes 2016-12-13 15:33:01 +01:00
Ralph Lange
fd53e175b4 Update CONFIG_BASE_VERSION for 3.15.5, remove "not released" from RELEASE_NOTES 2016-12-13 14:25:23 +01:00
Andrew Johnson
fab5ce675f Update comments in calcoutRecord 2016-12-12 17:44:01 -06:00
Andrew Johnson
85b5551b3b Merged final changes from 3.14.12.6 release 2016-12-09 17:27:35 -06:00
Andrew Johnson
260bc64b59 Set SNAPSHOT back to -DEV 2016-12-09 13:50:17 -06:00
Andrew Johnson
5097ac3230 Set SNAPSHOT for 3.14.12.6 2016-12-09 13:48:55 -06:00
Andrew Johnson
8d7bf52e51 One more cppcheck issue fixed 2016-12-09 11:17:43 -06:00
Andrew Johnson
a13416309c Merged asLib fix from 3.14 branch, to revno 12688 2016-12-08 14:00:52 -06:00
Andrew Johnson
1cb75ebb6e asLib message buffer too small (Freddie Akeroyd) 2016-12-08 13:57:23 -06:00
Andrew Johnson
63b059c35e Resolve additional cppcheck issues; fix iOS build 2016-12-07 17:51:00 -06:00
Andrew Johnson
dba6971e07 Merged changes from 3.14 branch to revno 12687 2016-12-07 16:36:58 -06:00
Andrew Johnson
94397b52fc Resolve some cppcheck errors & warnings 2016-12-07 13:53:26 -06:00
Andrew Johnson
7fe152ce1b Merge Bruce Hill's pcas-deadlock-fix-3.14 branch 2016-12-07 10:43:06 -06:00
Bruce Hill
d3568605ce Fetch nativeCount() in casChannelI constructor to avoid deadlock
if we fetch it from eventSysProcess()
2016-12-06 13:43:59 -08:00
Andrew Johnson
666721c7ad Document caput scalar arg's, update usage docs 2016-12-06 12:16:35 -06:00
Andrew Johnson
c3bb2bf2c2 Merged changes from 3.14 branch to revno 12682 2016-11-30 12:04:00 -06:00
0f7f4710c6 PCAS dynamic array support for GDD container types 2016-11-30 11:58:24 -06:00
Ralph Lange
2841af7069 rec: add promptgroups for OFFS and SHFT of fanout and seq 2016-11-29 14:48:57 +01:00
Andrew Johnson
0a4981093a Update mingw32 cross-target name for RHEL7 2016-11-15 17:44:21 -06:00
Andrew Johnson
726d7c6715 Fix chfPluginTest for MS 2015 compiler 2016-11-15 10:34:10 -06:00
Andrew Johnson
f1439f8b1c Fix epicsStdioTest for MS 2015 compiler 2016-11-15 09:56:42 -06:00
Andrew Johnson
aa6e976f92 Add .local includes to makeBaseApp templates 2016-11-04 17:18:14 -05:00
Andrew Johnson
3e0ddbb542 Set snapshot to -rc1-DEV 2016-10-31 18:06:50 -05:00
Andrew Johnson
67daaaa9b7 Set snapshot to -rc1-DEV 2016-10-31 17:06:19 -05:00
Andrew Johnson
a36443557b Set version to 3.14.12.6-rc1 2016-10-31 17:03:35 -05:00
Michael Davidsaver
99500b9be4 dbStatic: more informative error for bad field value 2016-09-18 17:35:19 -04:00
Michael Davidsaver
0821c8c4ff dbStatic: dbPutStringNum(, "") not an error
Restore previous behavour that empty string
is equivalent to numeric zero.

epicsParse*() returns S_stdlib_noConversion
where previously strtoul() did not.

Conflicts:
	src/ioc/db/test/Makefile
2016-09-12 18:20:02 -04:00
Andrew Johnson
da5455ed22 Fixes for Windows builds 2016-09-09 11:14:59 -05:00
Andrew Johnson
58c78af4f9 Initialize all fields of jlink, link types may not use calloc 2016-09-07 23:35:39 -05:00
Andrew Johnson
813166128e Merged changes from 3.15 branch, to revno 12781 2016-09-07 10:04:54 -05:00
Andrew Johnson
b2012fdfb5 Added test link type, fix dbPutLinkTest for JSON_LINKs 2016-09-07 00:50:40 -05:00
Andrew Johnson
c12a35e388 Clean up memory leaks 2016-09-07 00:47:51 -05:00
Andrew Johnson
8a9707e74f Fixed a small memory leak in lnkCalc 2016-09-06 22:28:36 -05:00
Andrew Johnson
2d4301f0bb Fix warnings from clang 2016-09-05 22:36:45 -05:00
Andrew Johnson
268e59b052 Minor updates 2016-09-05 15:38:16 -05:00
Andrew Johnson
5b74799605 Some documentation updates 2016-09-05 15:12:09 -05:00
Andrew Johnson
cd49e245c2 Added JLink reporting infrastructure
Command 'dbjlr <record|*> <level>' calls the report method for
all JSON links in all records, or in one named record.
Added level and indent arguments to the jlif::report() method.

Added jlif::map_children() method for recursing through all
JSON links, plus dbJLinkMapChildren() and dbJLinkMapAll() APIs.

Implemented the report and map_children methods in the const
and calc link types.
2016-09-05 14:25:33 -05:00
Andrew Johnson
19447dc7ff Make the long-string buffer for link fields bigger
When representing a link field as a long string (.INP$)
we have to pick some size limit for the buffer.
Previously this was the max length of a PV name + 12 chars,
but with JSON links that's not big enough.

This commit sets it to 1KB and defines a macro so it will be
easier to change in the future if necessary.
2016-09-04 16:56:15 -05:00
Andrew Johnson
dd311be319 JLink: Convert parser->linkDepth into jlink->parseDepth
This counter is indicates when we've finished parsing a link,
and needs to be stored with link rather than the parser so it
keeps its value while parsing embedded links. This fixes the
embedded links bug.

Also removed the limit on a link name's length.
2016-09-04 16:33:10 -05:00
Andrew Johnson
4448317d73 Add lnkConst_remove, fix debug messages 2016-09-04 16:02:59 -05:00
Andrew Johnson
ec6d86c91c Fix jlink memory leak in dbStaticLib
Added dbFreeLinkInfo(), use everywhere to release dbLinkInfo resources.

Renamed link_type => expected_type in db[Can]SetLink(),
my brain understands this name faster.
2016-09-04 15:56:39 -05:00
Andrew Johnson
4302da3628 Minor fixes to the calc link-type 2016-09-03 22:24:55 -05:00
Andrew Johnson
25315882ec Clean up JSON_LINKs in doCloseLinks 2016-09-03 22:22:12 -05:00
Andrew Johnson
f8d6cd98a0 Minor cleanups 2016-09-03 19:44:49 -05:00
Andrew Johnson
5fe3e8bfb5 Added calc link-type 2016-09-03 19:22:55 -05:00
Andrew Johnson
8d1c416551 Moved PV_LINK-specific code out of dbLink.c into link types
This required a change to the lset::getValue arguments, removing
the pstat and psevr pointers. Links can still return a non-zero
value from getValue and trigger a LINK:INVALID alarm, but for any
other alarm settings they must manipulate the record themselves.
2016-09-03 19:21:11 -05:00
Andrew Johnson
07b09eed1f Fixes to dbJLink, added dbJLinkFree()
Moved the clearing of key_is_link to the right place,
embedded links now parse correctly.
2016-09-03 13:36:17 -05:00
Andrew Johnson
1e1c52cb69 Use new epicsStrnDup() API 2016-09-03 13:27:30 -05:00
Andrew Johnson
6e88d48615 Added epicsStrnDup() and dbmfStrndup() routines
The JSON parser passes string arguments with a length
instead or nil-terminating them. These routines make it
simple to copy such strings into either permanent or
temporary storage.
2016-09-03 13:25:19 -05:00
Andrew Johnson
23c71e9965 Various improvements
* Added new lset::openLink() method, called on JSON_LINKs only
* Cleanup in dbJLink.c to prevent memory leaks.
* Removed jlif::start_parse() method.
* Renamed jlif::end_parse() to end_child, which will be called on
the parent link when a child link has succesfully finished parsing.
2016-09-01 23:21:23 -05:00
Andrew Johnson
3992d4b92a Split dbJLinkInit, JLinks are now parsed at load-time 2016-09-01 00:56:26 -05:00
Andrew Johnson
40a3a66745 Added loadLS routine to lset
The long string in/out records use a different initializer
for constant links. The new loadLS method allows a constant
link type to initialize such a long string field.

NB: This routine was added in the middle of the lset table.
Any external link support implementations must be adjusted.
2016-08-31 00:36:23 -05:00
Andrew Johnson
d0dcd61b23 Add code for arrays of strings 2016-08-30 23:03:08 -05:00
Andrew Johnson
5ec0633282 Pass link dbfType to jlif allocator; needed! 2016-08-30 01:13:15 -05:00
Andrew Johnson
33e565b67d Fix build warning from clang 2016-08-29 10:41:51 -05:00
Andrew Johnson
7edc0c67ca JSON Links implementation
The lnkConst.c implementation is not yet complete, no support for arrays of
strings (JMOP).

Link error messages should display their record & field name, which is not yet
possible.

The ability to embed links as parameters to other link types is not complete
yet; this will be required for the calc link type.

This code currently passes all existing tests, but additional tests are needed
for the new functionality.
2016-08-29 01:12:09 -05:00
Andrew Johnson
056edc0d8a Undo buggy change 2016-08-28 23:41:35 -05:00
Andrew Johnson
fc66793ee2 Start documenting changes 2016-08-27 16:31:49 -05:00
Andrew Johnson
37b6cbb50c Use new dbLink APIs instead of checking link.type 2016-08-27 16:30:48 -05:00
Andrew Johnson
cca6a5d05a Add isConstant and isVolatile to LSET 2016-08-27 16:26:55 -05:00
Andrew Johnson
82385c9f1b Missed a spot handling JSON_LINK field values 2016-08-18 00:18:41 -05:00
Andrew Johnson
cbc7af0ef8 Remove 2 obsolete dbStatic routines (forms) 2016-08-15 20:19:19 -05:00
Andrew Johnson
bed1c618a8 Use dbPutLinkAsync() in all output SoftCallback dev's 2016-08-13 21:53:31 -05:00
Andrew Johnson
7df97f074e Add lset::dbPutLinkAsync and S_db_noLSET 2016-08-13 21:42:23 -05:00
Andrew Johnson
fe71fc98b8 Undo a small & unnecessary behaviour change 2016-08-12 23:53:42 -05:00
Andrew Johnson
d3a9ba7701 Fix issues related to const array initialization 2016-08-12 23:21:26 -05:00
Andrew Johnson
bb58598eba A cleaner way to close CA & DB links 2016-08-12 23:20:24 -05:00
Michael Davidsaver
899feb24b2 iocInit: close CA_LINKs through lset 2016-08-12 19:50:17 -04:00
Andrew Johnson
fb785e45c7 Adjust record and device support for array constants 2016-08-10 12:53:39 -05:00
Andrew Johnson
519208833f Add lset::loadArray and JSON parsing
Replace lset::loadLink with lset::loadScalar, add lset::loadArray
Add dbLoadLinkArray() routine to dbLink.h API
New dbConvertJSON.h API for use by dbConstLoadArray()
2016-08-10 12:49:49 -05:00
Andrew Johnson
ae2180f5b5 Comments in Makefile 2016-08-10 12:21:03 -05:00
Andrew Johnson
dafe2a83a3 libCom: Make yajl_alloc.h usable 2016-08-10 12:19:53 -05:00
Michael Davidsaver
ebfaca8228 cas: ignore CA client version older than v4.4
CAS ignore search and version messages
from CA minor versions older than 4.4.
2016-07-30 11:45:42 -04:00
Michael Davidsaver
da78e01e89 rsrv: remove !CA_V44() code
Remove code supporting deprecated
CA minor versions < 3
2016-07-31 19:49:08 -04:00
Michael Davidsaver
caf70216d3 rsrv: no ca exception response to UDP 2016-07-31 19:35:25 -04:00
Michael Davidsaver
95fd255dd6 rsrv: ignore CA client version older than v4.4
RSRV ignore search and version messages
from CA minor versions older than 4.
2016-07-30 10:35:49 -04:00
Michael Davidsaver
2dd16f4362 cas: honor DOREPLY for TCP searches 2016-07-31 15:10:36 -04:00
Michael Davidsaver
4c2b8819cd cas: ignore echo and unexpected UDP
Ignore UDP echo.
By default, don't log unexpected/invalid
UDP messages.
2016-07-30 11:46:28 -04:00
Michael Davidsaver
8992d5a593 rsrv: send channel create failure 2016-07-30 12:09:33 -04:00
Michael Davidsaver
802f29df47 rsrv: UDP search ignore DOREPLY
Don't send notice of failure
for lookup via. UDP.
2016-07-30 10:46:21 -04:00
Michael Davidsaver
16c419350b rsrv: ignore echo and unexpected UDP
Ignore UDP echo.
By default, don't log unexpected/invalid
UDP messages.
2016-07-30 10:41:39 -04:00
Andrew Johnson
935ab02bc1 Fix build failure on Solaris 2016-06-07 12:31:15 -05:00
Andrew Johnson
63d8651474 Make Perl DB parser handle duplicates and rtyp '*' 2016-06-07 01:00:38 -05:00
Andrew Johnson
c01967d64f Remove spurious include dbCa.h 2016-06-02 22:29:45 -05:00
Andrew Johnson
d1986edd9e Simplify link-type checks in record supports 2016-06-02 22:22:11 -05:00
Andrew Johnson
7627454f63 Simplify link-type checks in soft device supports 2016-06-02 22:02:54 -05:00
Andrew Johnson
667f74759d Allow (discard) comments inside JSON 2016-06-01 15:46:24 -05:00
Andrew Johnson
1f726c8760 Recognize arrays as constant links 2016-05-24 12:01:38 +02:00
Andrew Johnson
08b7802009 Recognize numbers before barewords 2016-05-24 11:59:08 +02:00
Andrew Johnson
f6c4099634 Make info tags also JSON objects 2016-05-23 12:00:11 +02:00
Andrew Johnson
c76041b14c Rename JSON_STR to JSON_LINK 2016-05-20 20:32:39 -05:00
Andrew Johnson
7ea544673a Accept bareword JSON strings, quote them 2016-05-20 00:02:45 -05:00
Andrew Johnson
6e6ae4354b Fix warnings from dbmfStrdup() change 2016-05-19 14:01:05 -05:00
Andrew Johnson
61e82ee1ae Fix memory allocation bugs 2016-05-19 01:32:12 -05:00
Andrew Johnson
28b3b1678c ioc/dbStatic: Add JSON parsing of field values
The parsing removes all white-space outside of quotes from the JSON.
dbRecordField() now strips quotes from simple string values itself.
2016-05-19 01:15:33 -05:00
Andrew Johnson
efb5ba27ae libCom/dbmf: Add dbmfStrcat3() for JSON parsing
Also removed all epicsShareAPI attributes
Made string arguments const char *
2016-05-19 00:58:45 -05:00
Andrew Johnson
574db56740 Make antelope's error messages slightly nicer 2016-05-19 00:51:23 -05:00
Andrew Johnson
998c3c1648 Clean up warnings from gcc 5.2 2016-05-16 14:55:58 -05:00
Andrew Johnson
6a592dc2c0 Support "link(name, lset)" syntax in DBD files
Both Perl and dbStaticLib support included.
Also added a new std/link directory for link types.
Nothing looks up the registered link support tables yet.
2016-05-08 22:57:42 -05:00
Andrew Johnson
ac5c7b0314 Merged Michael's cxxcleanup branch 2016-05-04 17:50:59 -05:00
Michael Davidsaver
d674866219 epicsGuard.h add typedefs linking guard and release 2016-05-02 20:53:51 -04:00
Michael Davidsaver
a1bd644502 drop all templateInstances.cpp
No longer needed by any targets.
2016-05-02 20:51:11 -04:00
Michael Davidsaver
a38dccfb1a add guard/release typedefs for epicsMutex 2016-04-28 09:20:13 -04:00
Michael Davidsaver
17edfd0652 use epicsMin/Max instead of tsMin/Max
Don't remove tsMinMax.h yet as it appeared
in caServerApp template.
2016-04-28 09:20:13 -04:00
Michael Davidsaver
afd48be98c drop unused tsBTree.h 2016-04-28 09:20:13 -04:00
Michael Davidsaver
d92af8c44d remove unused autoPtrDestroy.h 2016-04-28 09:20:13 -04:00
Michael Davidsaver
2af37d076d drop unused epicsOnce 2016-04-28 09:20:13 -04:00
Michael Davidsaver
64c1a28f69 remove unused locationException.h includes 2016-04-28 09:20:13 -04:00
Michael Davidsaver
954874dbd6 drop epicsMemory.h 2016-04-28 09:20:13 -04:00
Michael Davidsaver
673cb24fc2 replace use of epics_auto_ptr w/ eapt_array
add helpers for udpiiu to calculate parameters maxPeriod and nTimers,
allowing them to be const.
Add SearchArray to hold fixed-size array of auto_ptr.
2016-04-28 09:20:13 -04:00
Michael Davidsaver
05c347434b use auto_ptr instead of epics_auto_ptr where applicable 2016-04-28 09:20:13 -04:00
Andrew Johnson
13294f80cc Add basic support and tests for a JSON link address type 2016-04-27 20:47:17 -05:00
Andrew Johnson
778aa18c00 More cleanup 2016-04-27 20:29:16 -05:00
Andrew Johnson
0348c2295b Cleanup 2016-04-26 22:13:12 -05:00
Andrew Johnson
8a5d1a08ad Restore loadLink to lset, move CONSTANT link code into its own source file 2016-04-03 01:29:28 -05:00
Andrew Johnson
1e028d68d8 Move DBLINK support code into its own source file 2016-04-03 00:49:36 -05:00
Andrew Johnson
d33c402b00 Release Notes 2016-03-23 17:15:57 -05:00
Andrew Johnson
bc2a47b849 cvtFastPerform: Rename reserved member names, fix for vxWorks 2016-03-23 16:56:34 -05:00
Andrew Johnson
0a0b9a93a2 Simplify epicsConvertDoubleToFloat() 2016-03-22 18:14:12 -05:00
Andrew Johnson
d949e34c13 More cvtFastPerform changes
Added a converter using std::streambuf (slow!)
Pass buffer size to converters
Added verbose flag and # numbers to measure
Do the small number tests first
2016-03-22 17:47:03 -05:00
Andrew Johnson
db4f208659 Collate and report by precision 2016-03-22 01:01:51 -05:00
Andrew Johnson
e82449171f Restructure cvtFastPerform, fix VxWorks build 2016-03-18 17:45:52 -05:00
Andrew Johnson
e7bba39737 Add int64 record types and device support, from long 2016-03-16 13:14:49 -05:00
Andrew Johnson
f97c1a345e Fix cvtFast and tests
We might still want to change the actual behaviour though,
see the FIXME comments.
2016-03-16 09:44:35 -05:00
Andrew Johnson
4a5a675ef8 Remove development printf() statements 2014-08-24 23:48:32 -05:00
Andrew Johnson
2d4243981f Fix warnings found by clang 2014-07-12 01:12:08 -05:00
Andrew Johnson
2fb0b0763d Implement 64-bit database field types.
Incorporates major reworking of the dbConvert.c file.
if the 64-bit stuff gets rejected most of that should
get pulled in anyway.
2014-07-10 18:13:28 -05:00
Michael Davidsaver
428268a71e rsrv: avoid strlen() on possible unterminated strings
Detect these w/o risk of SIGSEGV
2014-01-11 10:59:57 -05:00
Michael Davidsaver
746c739769 add epicsStrnLen()
Base currently requires only POSIX 2001 while
strnlen() is part of POSIX 2008.
2014-01-11 10:58:39 -05:00
479 changed files with 31337 additions and 15542 deletions

View File

@@ -1,9 +0,0 @@
./bin
./lib
./db
./dbd
./html
./include
./templates
**/O.*
./QtC-*

12
.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
/cfg/
/bin/
/lib/
/db/
/dbd/
/html/
/include/
/templates/
O.*/
/QtC-*
*.orig
*.log

32
.travis.yml Normal file
View File

@@ -0,0 +1,32 @@
sudo: false
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:
- libreadline6-dev
- libncurses5-dev
- perl
- clang
- g++-mingw-w64-i686
- bison
- flex
- texinfo
- install-info
cache:
directories:
- $HOME/.cache
install: sh ci/travis-prepare.sh </dev/null
script: sh ci/travis-build.sh </dev/null

10
README
View File

@@ -2,14 +2,14 @@
EPICS Base - the central core of a control system toolkit
---------------------------------------------------------
Copyright (c) 1991-2003 The University of Chicago, as Operator
of Argonne National Laboratory.
Copyright UChicago Argonne LLC, 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 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.
EPICS Base is distributed subject to a Software License
Agreement found in the file LICENSE that is included with
this distribution.
---------------------------------------------------------

86
appveyor.yml Normal file
View File

@@ -0,0 +1,86 @@
# AppVeyor configuration for EPICS Base
# Ralph Lange <ralph.lange@gmx.de>
# Copyright (c) 2016-2017 ITER Organization
# Version format
version: base-{branch}-{build}
#---------------------------------#
# repository cloning #
#---------------------------------#
# Called at very beginning, before repo cloning
init:
# Set autocrlf to make batch files work
- git config --global core.autocrlf true
# Set clone depth (do not fetch complete history)
clone_depth: 2
# Skipping commits affecting only specific files
skip_commits:
files:
- 'documentation/*'
- 'templates/*'
- '**/*.html'
- '**/*.md'
#---------------------------------#
# build matrix configuration #
#---------------------------------#
# Build Configurations: dll/static, regular/debug
configuration:
- dynamic
- static
- dynamic-debug
- static-debug
# Environment variables: compiler toolchain
environment:
matrix:
- TOOLCHAIN: 9.0
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
- TOOLCHAIN: cygwin
- TOOLCHAIN: mingw
# Platform: architecture
platform:
- x86
- x64
# Matrix configuration: allow specific failing jobs
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- platform: x64
TOOLCHAIN: 9.0
- platform: x64
TOOLCHAIN: 10.0
#---------------------------------#
# building & testing #
#---------------------------------#
install:
- cmd: ci/appveyor-prepare.bat
build_script:
- cmd: ci/appveyor-make.bat
test_script:
- cmd: ci/appveyor-make.bat runtests
#---------------------------------#
# notifications #
#---------------------------------#
notifications:
- provider: Slack
incoming_webhook:
secure: RYOm3FIUYeZGjWKaeTVKwq+C3fzK54AKwbmAoECED45mex3lN+8HmrC845a6mg9xPUJ/ND51RopWVaKDD9/UzaM0SO195RQLKqUTIUafiuM=

116
ci/appveyor-make.bat Normal file
View File

@@ -0,0 +1,116 @@
:: 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]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
:: All command line args are passed to make
Setlocal EnableDelayedExpansion
set "ST="
if /i "%CONFIGURATION%"=="static" set ST=-static
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
:: Use parallel make, except for 3.14
set "MAKEARGS=-j2 -Otarget"
if "%APPVEYOR_REPO_BRANCH%"=="3.14" set MAKEARGS=
if "%TOOLCHAIN%"=="cygwin" (
set "MAKE=make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=cygwin-x86_64"
set "INCLUDE=C:\cygwin64\include;%INCLUDE%"
set "PATH=C:\cygwin64\bin;%PATH%"
echo [INFO] Cygwin Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=cygwin-x86"
set "INCLUDE=C:\cygwin\include;%INCLUDE%"
set "PATH=C:\cygwin\bin;%PATH%"
echo [INFO] Cygwin Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
if "%TOOLCHAIN%"=="mingw" (
set "MAKE=mingw32-make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=windows-x64-mingw"
set "INCLUDE=C:\tools\mingw64\include;%INCLUDE%"
set "PATH=C:\tools\mingw64\bin;%PATH%"
echo [INFO] MinGW Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=win32-x86-mingw"
set "INCLUDE=C:\tools\mingw32\include;%INCLUDE%"
set "PATH=C:\tools\mingw32\bin;%PATH%"
echo [INFO] MinGW Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
set "MAKE=C:\tools\make"
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
where cl
if !ERRORLEVEL! NEQ 0 (
call "%VSINSTALL%\VC\vcvarsall.bat" x86_amd64
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
)
goto MSFound
)
if exist "%VSINSTALL%\VC\bin\amd64\vcvars64.bat" (
call "%VSINSTALL%\VC\bin\amd64\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
) else (
set EPICS_HOST_ARCH=win32-x86%ST%
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
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\Common7\Tools\vsvars32.bat" (
call "%VSINSTALL%\Common7\Tools\vsvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
)
:MSMissing
echo [INFO] Installation for MSVC Toolchain %TOOLCHAIN% / %OS% seems to be missing
exit 1
:MSFound
echo [INFO] Microsoft Visual Studio Toolchain %TOOLCHAIN%
echo [INFO] Compiler Version
cl
:Finish
echo [INFO] EPICS_HOST_ARCH: %EPICS_HOST_ARCH%
echo [INFO] Make version
%MAKE% --version
%MAKE% %MAKEARGS% %*

70
ci/appveyor-prepare.bat Normal file
View File

@@ -0,0 +1,70 @@
:: Build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static, -debug]
:: PLATFORM - "x86" -> use 32bit architecture
::
:: Prepares an Appveyor build by excuting the following steps
:: - Set up configure\CONFIG_SITE for static vs. dynamic build
:: - Install Cygwin / Mingw (TOOLCHAIN setting) in the in the appropriate flavor
:: - Download and install Make-4.1 from EPICS download page
Setlocal EnableDelayedExpansion
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
if "%TOOLCHAIN%"=="cygwin" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing Cygwin 64bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86_64.exe', 'C:\cygwin64\setup-x86_64.exe')"
C:\cygwin64\setup-x86_64.exe -q -P "libreadline-devel,libncursesw-devel"
) else (
echo [INFO] Installing Cygwin 32bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86.exe', 'C:\cygwin\setup-x86.exe')"
C:\cygwin\setup-x86.exe -q -P "libreadline-devel,libncursesw-devel"
)
)
if "%TOOLCHAIN%"=="mingw" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing MinGW 64bit
cinst mingw || cinst mingw
) else (
echo [INFO] Installing MinGW 32bit
cinst mingw --x86 || cinst mingw --x86
)
)
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')"
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip

90
ci/travis-build.sh Normal file
View File

@@ -0,0 +1,90 @@
#!/bin/sh
set -e -x
die() {
echo "$1" >&2
exit 1
}
ticker() {
while true
do
sleep 60
date -R
[ -r "$1" ] && tail -n10 "$1"
done
}
CACHEKEY=1
EPICS_HOST_ARCH=`sh startup/EpicsHostArch`
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
case "$CMPLR" in
clang)
echo "Host compiler is clang"
cat << EOF >> configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
GNU = NO
CMPLR_CLASS = clang
CC = clang
CCC = clang++
EOF
;;
*) echo "Host compiler is default";;
esac
if [ "$STATIC" = "YES" ]
then
echo "Build static libraries/executables"
cat << EOF >> configure/CONFIG_SITE
SHARED_LIBRARIES=NO
STATIC_BUILD=YES
EOF
fi
# requires wine and g++-mingw-w64-i686
if [ "$WINE" = "32" ]
then
echo "Cross mingw32"
sed -i -e '/CMPLR_PREFIX/d' configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
cat << EOF >> configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
CMPLR_PREFIX=i686-w64-mingw32-
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
EOF
fi
# set RTEMS to eg. "4.9" or "4.10"
# requires qemu, bison, flex, texinfo, install-info
if [ -n "$RTEMS" ]
then
echo "Cross RTEMS${RTEMS} for pc386"
install -d /home/travis/.cache
curl -L "https://github.com/mdavidsaver/rsb/releases/download/travis-20160306-2/rtems${RTEMS}-i386-trusty-20190306-2.tar.gz" \
| tar -C /home/travis/.cache -xj
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' configure/os/CONFIG_SITE.Common.RTEMS
cat << EOF >> configure/os/CONFIG_SITE.Common.RTEMS
RTEMS_VERSION=$RTEMS
RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
EOF
# find local qemu-system-i386
export PATH="$HOME/.cache/qemu/usr/bin:$PATH"
echo -n "Using QEMU: "
type qemu-system-i386 || echo "Missing qemu"
EXTRA=RTEMS_QEMU_FIXUPS=YES
fi
make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make tapfiles
find . -name '*.tap' -print0 | xargs -0 -n1 prove -e cat -f
fi

40
ci/travis-prepare.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/sh
set -e -x
die() {
echo "$1" >&2
exit 1
}
CURDIR="$PWD"
QDIR="$HOME/.cache/qemu"
if [ -n "$RTEMS" -a "$TEST" = "YES" ]
then
git clone --quiet --branch vme --depth 10 https://github.com/mdavidsaver/qemu.git "$HOME/.build/qemu"
cd "$HOME/.build/qemu"
HEAD=`git log -n1 --pretty=format:%H`
echo "HEAD revision $HEAD"
[ -e "$HOME/.cache/qemu/built" ] && BUILT=`cat "$HOME/.cache/qemu/built"`
echo "Cached revision $BUILT"
if [ "$HEAD" != "$BUILT" ]
then
echo "Building QEMU"
git submodule --quiet update --init
install -d "$HOME/.build/qemu/build"
cd "$HOME/.build/qemu/build"
"$HOME/.build/qemu/configure" --prefix="$HOME/.cache/qemu/usr" --target-list=i386-softmmu --disable-werror
make -j2
make install
echo "$HEAD" > "$HOME/.cache/qemu/built"
fi
fi
cd "$CURDIR"

View File

@@ -3,13 +3,12 @@
# 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
# EPICS BASE is 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)
@@ -19,12 +18,12 @@ ifdef T_A
endif
#---------------------------------------------------------------
# Epics base Ioc libraries
# EPICS Base Ioc libraries
EPICS_BASE_IOC_LIBS += dbRecStd dbCore ca Com
#---------------------------------------------------------------
# Epics base Host libraries
# EPICS Base Host libraries
EPICS_BASE_HOST_LIBS += cas gdd
EPICS_BASE_HOST_LIBS += ca Com
@@ -37,17 +36,16 @@ ifdef BASE_TOP
SHRLIB_VERSION = $(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION)
# Windows only allows 2 levels of version numbering
PROD_VERSION = $(EPICS_VERSION).$(EPICS_REVISION)
BASE_CPPFLAGS += -DUSE_TYPED_RSET
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))
#---------------------------------------------------------------
@@ -59,7 +57,7 @@ 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
MAKEBPT = $(TOOLS)/makeBpt$(HOSTEXE)
DBEXPAND = $(PERL) $(TOOLS)/dbdExpand.pl
@@ -68,11 +66,11 @@ DBTOMENUH = $(PERL) $(TOOLS)/dbdToMenuH.pl
REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG)
#-------------------------------------------------------
#---------------------------------------------------------------
# tools for installing libraries and products
INSTALL_QUIETLY := $(if $(findstring s,$(MAKEFLAGS)),-q,)
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(INSTALL_QUIETLY)
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(QUIET_FLAG)
INSTALL_PRODUCT = $(INSTALL)
INSTALL_LIBRARY = $(INSTALL)
@@ -82,7 +80,7 @@ MKMF = $(PERL) $(TOOLS)/mkmf.pl
REPLACEVAR = $(PERL) $(TOOLS)/replaceVAR.pl
#---------------------------------------------------------------
# private versions of lex/yacc from EPICS
# Our versions of lex (flex) and yacc (antelope)
EYACC = $(TOOLS)/antelope$(HOSTEXE)
ELEX = $(TOOLS)/e_flex$(HOSTEXE) -S$(EPICS_BASE)/include/flex.skel.static
@@ -90,28 +88,6 @@ YACC = $(EYACC)
LEX = $(ELEX)
#---------------------------------------------------------------
# Our use of msi is incompatible with older versions
# The 3.15 version of msi supports new options
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,19 +15,30 @@
# EPICS_SITE_VERSION is defined in CONFIG_SITE for sites that want a local
# version number to be included in the reported version string.
# 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.
# 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.
BASE_3_14 = NO
BASE_3_15 = YES
BASE_3_15 = NO
BASE_3_16 = YES
# EPICS_VERSION must be a number >0 and <256
EPICS_VERSION = 3
# EPICS_REVISION must be a number >=0 and <256
EPICS_REVISION = 15
EPICS_REVISION = 16
# EPICS_MODIFICATION must be a number >=0 and <256
EPICS_MODIFICATION = 5
EPICS_MODIFICATION = 1
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero

View File

@@ -38,10 +38,6 @@ 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
@@ -83,6 +79,7 @@ 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
@@ -332,6 +329,14 @@ 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,8 +35,10 @@ 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=""

View File

@@ -58,8 +58,11 @@ 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,10 +8,12 @@
#*************************************************************************
#RULES.Db
# Set db substitutions file suffix
# Set db substitutions and template file suffixes
SUBST_SUFFIX ?= .substitutions
TEMPL_SUFFIX ?= .template
##################################################### vpath
#---------------------------------------------------------------
# vpath
vpath %.pm $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
vpath %.pod $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
@@ -19,12 +21,13 @@ 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 %.template $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %$(TEMPL_SUFFIX) $(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)
@@ -33,13 +36,15 @@ 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
@@ -86,31 +91,28 @@ 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)/*.template
$(COMMON_DIR)/*$(SUBST_SUFFIX) $(COMMON_DIR)/*$(TEMPL_SUFFIX)
# 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 .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
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))
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)
@@ -123,7 +125,8 @@ ACF_INCLUDES = -I. $(TARGET_INCLUDES) $(USR_INCLUDES)\
ACFDEPENDS_CMD = $(MKMF) -m $@ $(ACF_INCLUDES) $(COMMONDEP_TARGET) $<
ACF_CMD = $(CPP) $(ACF_CPPFLAGS) $(ACF_INCLUDES) $< > $@
##################################################### dependancies
#---------------------------------------------------------------
# dependencies
HINC += $(addsuffix .h,$(DBDINC_NAME))
COMMON_DBDINC += $(addprefix $(COMMON_DIR)/,$(HINC))
@@ -133,12 +136,12 @@ DBDDEPENDS_FILES += $(addsuffix $(DEP),$(HINC) \
$(patsubst $(COMMON_DIR)/%,%, \
$(filter-out $(COMMON_DIR)/bpt%.dbd,$(COMMON_DBDS))))
#####################################################
#---------------------------------------------------------------
ifndef T_A
DEP = .d
TEMPLATE3+=$(addsuffix .template, $(TEMPLATE2))
TEMPLATE3 += $(addsuffix $(TEMPL_SUFFIX), $(TEMPLATE2))
COMMON_DIR = .
INSTALL_DBDS =
@@ -153,18 +156,13 @@ ACTIONS += install
ACTIONS += buildInstall
ACTIONS += runtests tapfiles
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
actionArchTargets = $(foreach action, $(ACTIONS), \
$(foreach arch, $(BUILD_ARCHS), $(action)$(DIVIDER)$(arch)))
cleanArchTargets = $(foreach arch, $(BUILD_ARCHS), clean$(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
@@ -172,20 +170,30 @@ buildInstall : build
rebuild: clean install
.PHONY: all host $(ACTIONS)
.PHONY: all $(ACTIONS)
$(actionArchTargets) $(BUILD_ARCHS): install
$(cleanArchTargets): clean
.PHONY: $(BUILD_ARCHS) $(actionArchTargets) $(cleanArchTargets)
endif # T_A defined
else
# T_A is defined
ifeq ($(EPICS_HOST_ARCH),$(T_A))
host: install
else
host:
endif
.PHONY: host
endif # T_A
ifneq (,$(strip $(DBDDEPENDS_FILES)))
-include $(DBDDEPENDS_FILES)
endif
##################################################### build dependancies, clean rule
#---------------------------------------------------------------
# build dependancies, clean rule
inc : $(COMMON_INC) $(INSTALL_INC)
@@ -205,7 +213,8 @@ db_clean :
realclean: clean
##################################################### Dependency files
#---------------------------------------------------------------
# Dependency files
%Record.h$(DEP): $(COMMON_DIR)/%Record.dbd
@$(RM) $@
@@ -256,19 +265,19 @@ menu%.h$(DEP): ../menu%.dbd
@$(DBEXPAND) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $($*_DBD) > $@
@echo "$(COMMONDEP_TARGET): ../Makefile" >> $@
%.db$(RAW)$(DEP): %$(SUBST_SUFFIX)
%.db$(DEP): %$(SUBST_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) -S$< $(TEMPLATE_FILENAME) > $@
%.db$(RAW)$(DEP): ../%$(SUBST_SUFFIX)
%.db$(DEP): ../%$(SUBST_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) -S$< $(TEMPLATE_FILENAME) > $@
%.db$(RAW)$(DEP): %.template
%.db$(DEP): %$(TEMPL_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) $< > $@
%.db$(RAW)$(DEP): ../%.template
%.db$(DEP): ../%$(TEMPL_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) $< > $@
@@ -282,14 +291,8 @@ menu%.h$(DEP): ../menu%.dbd
.PRECIOUS: %$(DEP)
##################################################### 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
#---------------------------------------------------------------
# Substitution files
# WARNING: CREATESUBSTITUTIONS script needs output dir on command line
@@ -310,25 +313,21 @@ $(INSTALL_DB)/%$(SUBST_SUFFIX): ../%$(SUBST_SUFFIX)
.PRECIOUS: $(COMMON_DIR)/%$(SUBST_SUFFIX)
##################################################### Template files
#---------------------------------------------------------------
# Template files
$(COMMON_DIR)/%.template: $(COMMON_DIR)/%.edf
@$(RM) $@
$(E2DB) $(E2DB_SYSFLAGS) $(E2DB_FLAGS) -n $@.VAR $<
@$(REPLACEVAR) < $@.VAR > $@
@$(RM) $@.VAR
$(INSTALL_DB)/%.template: %.template
$(INSTALL_DB)/%$(TEMPL_SUFFIX): %$(TEMPL_SUFFIX)
$(ECHO) "Installing template file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
$(INSTALL_DB)/%.template: ../%.template
$(INSTALL_DB)/%$(TEMPL_SUFFIX): ../%$(TEMPL_SUFFIX)
$(ECHO) "Installing template file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
.PRECIOUS: $(COMMON_DIR)/%.template
.PRECIOUS: $(COMMON_DIR)/%$(TEMPL_SUFFIX)
##################################################### INC files
#---------------------------------------------------------------
# INC files
$(COMMON_DIR)/%Record.h: $(COMMON_DIR)/%Record.dbd
@$(RM) $(notdir $@)
@@ -362,7 +361,8 @@ $(COMMON_DIR)/menu%.h: ../menu%.dbd
.PRECIOUS: $(COMMON_DIR)/%.h
##################################################### DBD files
#---------------------------------------------------------------
# DBD files
$(COMMON_DIR)/bpt%.dbd: bpt%.data
@$(RM) $(notdir $@)
@@ -425,7 +425,8 @@ $(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 $(TOOLS)/dbdToHtml.pl
@$(RM) $(notdir $@)
@@ -444,37 +445,44 @@ $(COMMON_DIR)/%.html: %.pm $(TOOLS)/podToHtml.pl
$(COMMON_DIR)/%.html: ../%.pm $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
$(PERL) $(TOOLS)/podToHtml.pl -s -o $(notdir $@) $<
@$(MKDIR) $(dir $@)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.html: ../%.pl $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PERL) $(TOOLS)/podToHtml.pl -s -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
.PRECIOUS: $(COMMON_DIR)/%.html %.html
##################################################### DB files
#---------------------------------------------------------------
# DB files
$(COMMON_DIR)/%.db$(RAW): $(COMMON_DIR)/%.edf
$(COMMON_DIR)/%.db: $(COMMON_DIR)/%.edf
$(E2DB) $(E2DB_SYSFLAGS) $(E2DB_FLAGS) -n $*.VAR $<
@$(REPLACEVAR) < $*.VAR > $@
@$(RM) $*.VAR
$(COMMON_DIR)/%.db$(RAW): %$(SUBST_SUFFIX)
$(COMMON_DIR)/%.db: %$(SUBST_SUFFIX)
$(ECHO) "Inflating database from $< $(TEMPLATE_FILENAME)"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) -S$< $(TEMPLATE_FILENAME)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db$(RAW): ../%$(SUBST_SUFFIX)
$(COMMON_DIR)/%.db: ../%$(SUBST_SUFFIX)
$(ECHO) "Inflating database from $< $(TEMPLATE_FILENAME)"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) -S$< $(TEMPLATE_FILENAME)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db$(RAW): %.template
$(COMMON_DIR)/%.db: %$(TEMPL_SUFFIX)
$(ECHO) "Inflating database from $<"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db$(RAW): ../%.template
$(COMMON_DIR)/%.db: ../%$(TEMPL_SUFFIX)
$(ECHO) "Inflating database from $<"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) $<
@@ -492,22 +500,6 @@ $(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)
@@ -515,7 +507,6 @@ $(INSTALL_DB)/%: %
$(INSTALL_DB)/%: ../%
$(ECHO) "Installing $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
endif
$(INSTALL_DB)/%.db: $(COMMON_DIR)/%.db
$(ECHO) "Installing created db file $@"
@@ -531,8 +522,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) $@
@@ -548,4 +539,3 @@ $(foreach file, $(DB_INSTALLS), $(eval $(call DB_INSTALLS_template, $(file))))
.PRECIOUS: %_registerRecordDeviceDriver.cpp
##################################################### END OF FILE

View File

@@ -14,7 +14,7 @@ build$(DIVIDER)$(ARCH) build: buildInstall
install$(DIVIDER)$(ARCH) install: buildInstall
$(ARCH): buildInstall
ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(ARCH))
ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(strip $(ARCH)))
buildInstall$(DIVIDER)$(ARCH) buildInstall: $(TARGETS)
clean$(DIVIDER)$(ARCH) clean:
@@ -35,4 +35,3 @@ envPaths: $(wildcard $(TOP)/configure/RELEASE*) \
realclean:
$(RM) cdCommands envPaths dllPath.bat relPaths.sh

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.
#*************************************************************************
#
# Rules for making things specified in Makefile
@@ -118,7 +118,7 @@ TAPFILES += $(TESTSCRIPTS:.t=.tap)
endif
#---------------------------------------------------------------
# Libraries
# Libraries
#
LIBTARGETS += $(LIBNAME) $(INSTALL_LIBS) $(TESTLIBNAME) \
@@ -129,16 +129,16 @@ LIBTARGETS += $(LIBNAME) $(INSTALL_LIBS) $(TESTLIBNAME) \
# Main targets
install: buildInstall
install: buildInstall
buildInstall : build
buildInstall: build
# Allows rebuild to work with parallel builds option, -j.
install: $(patsubst rebuild,clean,$(filter rebuild,$(MAKECMDGOALS)))
rebuild: clean install
build : inc
build: inc
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODNAME) \
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
@@ -171,7 +171,7 @@ ifdef RES
endif
$(DIRECTORY_TARGETS) :
$(MKDIR) -p $@
$(MKDIR) $@
# Install LIB_INSTALLS libraries before linking executables
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS)
@@ -188,7 +188,7 @@ warnRelease:
-$(CONVERTRELEASE) checkRelease
noCheckRelease:
ifeq ($(EPICS_HOST_ARCH),$(T_A))
@echo "Warning: RELEASE file consistency checks have been disabled"
$(info Warning: RELEASE file consistency checks have been disabled)
endif
#---------------------------------------------------------------
@@ -279,13 +279,17 @@ endif # RANLIB
$(SHRLIBNAME) $(DLLSTUB_LIBNAME) $(TESTSHRLIBNAME) $(TESTDLLSTUB_LIBNAME): \
$(LIBRARY_OBJS) $(LIBRARY_RESS) $(SHRLIB_DEPLIBS)
$(DLLSTUB_LIBNAME): $(SHRLIBNAME);
# Stub library timestamps may be earlier than the DLL itself.
# This order-only prerequisite resolves any related problems.
# The $(LINK.shrlib) command must build both library files if
# the target requires a separate stub library file.
$(DLLSTUB_LIBNAME): | $(SHRLIBNAME);
$(SHRLIBNAME): $(SHRLIB_PREFIX)%$(SHRLIB_SUFFIX):
@$(RM) $@
$(LINK.shrlib)
$(MT_DLL_COMMAND)
$(TESTDLLSTUB_LIBNAME): $(TESTSHRLIBNAME);
$(TESTDLLSTUB_LIBNAME): | $(TESTSHRLIBNAME);
$(TESTSHRLIBNAME): $(SHRLIB_PREFIX)%$(SHRLIB_SUFFIX):
@$(RM) $@
$(LINK.shrlib)
@@ -359,6 +363,14 @@ 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
@@ -492,7 +504,7 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
.PRECIOUS: $(COMMON_INC)
.PHONY: all host inc build install clean rebuild buildInstall build_clean
.PHONY: runtests tapfiles checkRelease warnRelease noCheckRelease
.PHONY: runtests tapfiles checkRelease warnRelease noCheckRelease FORCE
endif # BASE_RULES_BUILD
# EOF RULES_BUILD

View File

@@ -1,7 +1,7 @@
# CONFIG.Common.vxWorksCommon
#
# Definitions for vxWorks target archs
# Sites may override these definitions in CONFIG_SITE.Common.vxWorksCommon
# Override these definitions in CONFIG_SITE.Common.vxWorksCommon
# or CONFIG_SITE.<host>.vxWorksCommon
#-------------------------------------------------------
@@ -63,8 +63,6 @@ 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
@@ -80,30 +78,21 @@ VX_GNU_VERSION = $(VX_GNU_VERSION_$(VXWORKS_VERSION))
VX_GNU_MAJOR_VERSION = $(basename $(basename $(VX_GNU_VERSION)))
#--------------------------------------------------
# Fix WIND_BASE for vxWorks 6.x on linux
# NB: We know the value of WIND_HOST_TYPE here, but not VXWORKS_VERSION
# Fix old Linux WIND_HOST_TYPE
ifeq ($(WIND_HOST_TYPE),x86-linux)
WIND_HOST_TYPE_5 = x86-linux
WIND_HOST_TYPE_6 = x86-linux2
WIND_HOST_TYPE = $(WIND_HOST_TYPE_$(VXWORKS_MAJOR_VERSION))
WIND_HOST_TYPE = x86-linux2
endif
#--------------------------------------------------
# vxWorks directory definitions
VX_DIR_5 = $(WIND_BASE)
VX_DIR_6 = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
VX_DIR = $(VX_DIR_$(VXWORKS_MAJOR_VERSION))
VX_DIR = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
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))
GNU_TARGET_INCLUDE_DIR = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
#--------------------------------------------------
# vxWorks GNU directories
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))
GNU_DIR = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
#--------------------------------------------------
# Wind River moved nm out of GNU_BIN in some versions
@@ -123,9 +112,7 @@ NM = $(NM_DIR)/$(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
#--------------------------------------------------
# A linker script is essential for munching from vxWorks 6.6 onwards
# (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)
# (i.e. with versions that use gcc 4.1.2 or later).
MUNCH_LDFLAGS_6 = -T $(VX_DIR)/target/h/tool/gnu/ldscripts/link.OUT
MUNCH_LDFLAGS = $(MUNCH_LDFLAGS_$(VXWORKS_MAJOR_VERSION))
@@ -140,11 +127,10 @@ export TOOL_FAMILY = GNU
OP_SYS_CPPFLAGS += -DvxWorks=vxWorks
OP_SYS_CFLAGS += -fno-builtin
# Fix for vxWorks 5 headers that use macros defined in vxWorks.h but
# Fix for vxWorks 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 in
# both vxWorks 5 and 6.
# from defining the OFFSET macro, which generates lots of warnings.
OP_SYS_INCLUDE_CPPFLAGS += -include $(VX_DIR)/target/h/vxWorks.h
#--------------------------------------------------
@@ -157,7 +143,6 @@ 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
MKDIR = mkdir -p
RMDIR = rm -rf
CAT = cat

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -95,11 +95,12 @@ CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
# Compiler flags for C++ files
#
# -W<N> use warning level N
# (maximum lint level warnings at level 4)
# -w44355 set "'this' used in the base initializer list" to be level 4
# -W<n> disable warnings from levels > n
# -w<n><m> set warning m to level n
# -w44355 "'this' used in the base initializer list"
# -w44344 "behavior change: use of explicit template arguments results in ..."
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344
# -w44251 "class needs to have dll-interface to be used by clients of ..."
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251
WARN_CXXFLAGS_NO = -W1
#
@@ -165,48 +166,38 @@ EXE=.exe
OBJ=.obj
RES=.res
# Problem: MS Visual C++ does not recognize *.cc as C++ source,
# so we do C++ compiles using the global flag -TP
# MS Visual C++ doesn't recognize *.cc as a C++ source file,
# so C++ compiles get the flag -TP
COMPILER_CXXFLAGS = -TP
# Operating system flags
# Operating system flags
OP_SYS_CFLAGS =
OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
#
# Files and flags needed to link DLLs (used in RULES_BUILD)
#
WIN32_DLLFLAGS = /subsystem:windows /dll $(OPT_LDFLAGS) \
# Files and flags needed to link DLLs (used in RULES_BUILD)
WIN32_DLLFLAGS = -subsystem:windows -dll $(OPT_LDFLAGS) \
$(USR_LDFLAGS) $(CMD_LDFLAGS) $(TARGET_LDFLAGS) $(LIB_LDFLAGS)
#
# specify dll .def file only if it exists
#
# Specify dll .def file only if it exists
DLL_DEF_FLAG = $(addprefix -def:,$(wildcard ../$(addsuffix .def,$*)))
#
# A WIN32 dll has three parts:
# A WIN32 dll has three parts:
# x.dll: the real dll (SHRLIBNAME)
# x.lib: what you link to progs that use the dll (DLLSTUB_LIBNAME)
# x.exp: what you need to build the dll (in no variable)
#
LINK.shrlib = $(WINLINK) -nologo $(WIN32_DLLFLAGS) -out:$@ \
-implib:$(@:%$(SHRLIB_SUFFIX)=%$(LIB_SUFFIX)) \
$(DLL_DEF_FLAG) $(LIBRARY_LD_OBJS) $(LIBRARY_LD_RESS) $(SHRLIB_LDLIBS)
# adjust names of libraries to build
#
# Adjust names of libraries to build
SHRLIB_SUFFIX_BASE = .dll
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
SHRLIBNAME_YES = $(BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
LOADABLE_SHRLIBNAME = $(LOADABLE_BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
TESTSHRLIBNAME_YES = $(TESTBUILD_LIBRARY:%=%$(SHRLIB_SUFFIX_BASE))
#
# When SHARED_LIBRARIES is YES we are building a DLL link library
# and when SHARED_LIBRARIES is NO we are building an object library
#
# When SHARED_LIBRARIES is YES we are building a DLL shared library.
# When SHARED_LIBRARIES is NO we are building an object library
DLLSTUB_SUFFIX = .lib
DLLSTUB_LIBNAME_YES = $(BUILD_LIBRARY:%=%.lib)
DLLSTUB_LIBNAME = $(DLLSTUB_LIBNAME_$(SHARED_LIBRARIES))
@@ -220,7 +211,7 @@ LIBNAME = $(LIBNAME_$(SHARED_LIBRARIES))
TESTLIBNAME_NO = $(TESTBUILD_LIBRARY:%=%.lib)
TESTLIBNAME = $(TESTLIBNAME_$(SHARED_LIBRARIES))
# dll install location
# dll install location
INSTALL_SHRLIB = $(INSTALL_BIN)
@@ -280,7 +271,7 @@ LINK.cpp = $(WINLINK) -nologo $(STATIC_LDFLAGS) $(LDFLAGS) $(PROD_LDFLAGS) \
#--------------------------------------------------
# UseManifestTool.pl checks MS Visual c++ compiler version number to
# decide whether or not to use the Manifest Tool command to embed the
# linker created .manifest file into a library or product target.
# linker created .manifest file into a library or product target.
# useManifestTool.pl returns 0(don't use) or 1(use).
#
MT.exe = mt.exe -nologo -manifest $@.manifest
@@ -290,4 +281,3 @@ MT_EXE_COMMAND_NO = $(MT.exe) "-outputresource:$@;\#1"
MT_EXE_COMMAND1 = $(MT_EXE_COMMAND_$(STATIC_BUILD))
MT_DLL_COMMAND = $(MT_DLL_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
MT_EXE_COMMAND = $(MT_EXE_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))

View File

@@ -8,8 +8,7 @@
include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
-include $(CONFIG)/os/CONFIG_SITE.win32-x86.win32-x86
OPT_LDFLAGS += /MACHINE:X64
# /MACHINE:X64
# /MACHINE:IA64 (Itanium)
# /MACHINE:X86
OPT_LDFLAGS += -MACHINE:X64
# -MACHINE:X64
# -MACHINE:IA64 (Itanium)
# -MACHINE:X86

View File

@@ -1,25 +1,17 @@
# 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. However don't include any third-level digits
# (e.g. the .2 in 5.5.2) because we don't need them.
# need to know that. Do not include any third-level digits.
# Note: vxWorks 5.4.x (Tornado 2.0.x) is not supported
# 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.
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
#VXWORKS_VERSION = 6.9
VXWORKS_VERSION = 6.9
# Sites may override the following path for a particular host
@@ -27,10 +19,8 @@ VXWORKS_VERSION = 5.5
# 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)
WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
#WIND_BASE = /ade/vxWorks/$(VXWORKS_VERSION)
@@ -39,9 +29,9 @@ WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
#WORKBENCH_VERSION = 2.6
#WORKBENCH_VERSION = 3.0
#WORKBENCH_VERSION = 3.2
#WORKBENCH_VERSION = 3.3
WORKBENCH_VERSION = 3.3
# Utilities Version number, required from vxWorks 6.8 and later
#UTILITIES_VERSION = 1.0
UTILITIES_VERSION = 1.0

View File

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

View File

@@ -4,25 +4,36 @@
<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 R3.15.5</title>
<title>Known Problems in R3.16.1</title>
</head>
<body>
<h1 style="text-align: center">EPICS Base R3.15.5: Known Problems</h1>
<h1 style="text-align: center">EPICS Base R3.16.1: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-3.15.5 tree. Download them, then use the GNU Patch program as
base-3.16.1 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.5</b>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.16.1</b>
% <b>patch -p0 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following significant problems have been reported with this
version of EPICS Base:</p>
<p>The following problems were known by the developers at the time of this
release:</p>
<ul>
<li>None known as yet.</li>
<!-- Items added after release should be formatted thusly:
<li>YYYY-MM-DD: Description of 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>
</ul>

View File

@@ -1,24 +1,24 @@
Installation Instructions
EPICS Base Release 3.15.5
EPICS Base Release 3.16.1
--------------------------------------------------------------------------
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
*<EFBFBD>What is EPICS base?
*<EFBFBD>What is new in this release?
*<EFBFBD>Copyright
*<EFBFBD>Supported platforms
*<EFBFBD>Supported compilers
*<EFBFBD>Software requirements
*<EFBFBD>Host system storage requirements
*<EFBFBD>Documentation
*<EFBFBD>Directory Structure
*<EFBFBD>Build related components
*<EFBFBD>Building EPICS base (Unix and Win32)
*<EFBFBD>Example application and extension
*<EFBFBD>Multiple host platforms
--------------------------------------------------------------------------
@@ -85,17 +85,17 @@
as processes on the host platform.
vxWorks
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
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
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.
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.
Consult the vxWorks 6.x EPICS web pages 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

View File

@@ -9,7 +9,7 @@
<BODY>
<CENTER>
<H1>Installation Instructions</H1>
<H2>EPICS Base Release 3.15.5</H2><BR>
<H2>EPICS Base Release 3.16.1</H2><BR>
</CENTER>
<HR>
<H3> Table of Contents</H3>
@@ -90,17 +90,16 @@
as processes on the host platform.</P>
<P><B>vxWorks</B><BR>
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
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
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/tornado.php">vxWorks
5.x</a> or <a href="http://www.aps.anl.gov/epics/base/vxWorks6.php">vxWorks
6.x</a> EPICS web pages about and the vxWorks documentation for information
<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
about configuring your vxWorks operating system for use with EPICS.</P>
<P><B>RTEMS</B><BR>
@@ -191,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
@@ -207,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>
@@ -341,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
@@ -351,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,30 +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 new releases of EPICS Base.</p>
that should be performed when creating production 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 versions or Release Candidates by the
Release Manager. A Release Candidate that has received widespread testing for a
week without any additional problems being discovered or significant changes
being committed can be designated as the final release version.</p>
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
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 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>
<p>The following roles are used below:</p>
<dl>
<dt><strong>Release Manager</strong> (Ralph Lange)</dt>
<dt><strong>Release Manager</strong> ()</dt>
<dd>Responsible for managing and tagging the release</dd>
<dt><strong>Platform Developers</strong></dt>
<dt><strong>Platform Developers</strong> (optional)</dt>
<dd>Responsible for individual operating system platforms</dd>
<dt><strong>Application Developers</strong></dt>
<dd>Responsible for support modules that depend on EPICS Base.</dd>
@@ -90,7 +89,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Set the Feature Freeze date, by which time all Bazaar commits for
<td>Set the Feature Freeze date, by which time all Git commits for
enhancements and new functionality should have been completed. After
this date, commits should only be made to fix problems that show up
during testing.</td>
@@ -132,39 +131,40 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar, using these tag conventions:
<td>Tag the module in Git using these tag conventions:
<ul>
<li>
<tt>R3.15.5-pre<i>n</i></tt>
<tt>R3.16.1-pre<i>n</i></tt>
&mdash; pre-release tag
</li>
<li>
<tt>R3.15.5-rc<i>n</i></tt>
&mdash; release candidate tag, note the <tt>rc</tt> is now
lower-case</li>
<tt>R3.16.1-rc<i>n</i></tt>
&mdash; release candidate tag
</li>
</ul>
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.5-rc<i>n</i>
cd base-3.16<br />
git tag -m 'ANJ: Tagged for 3.16.1-rc1' R3.16.1-rc1
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Export the tagged version into a tarfile. Note that this command
generates a gzipped tarfile directly from the repository:
<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:
<blockquote><tt>
cd ~/base<br />
bzr export
--root=base-3.15.5-rc<i>n</i>
-r tag:R3.15.5-rc<i>n</i>
base-3.15.5-rc<i>n</i>.tar.gz
mirror-3.15
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
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.15.5-rc<i>n</i>.tar.gz
gpg --armor --sign --detach-sig base-3.16.1-rc1.tar.gz
</tt></blockquote>
</td>
</tr>
@@ -258,7 +258,7 @@ relevent roles unless the Release Manager designates otherwise:</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>
@@ -273,29 +273,30 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar:
<td>Tag the module in Git:
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.5</i>
cd base-3.16<br />
git tag -m 'ANJ: Tagged for 3.16.1' R3.16.1</i>
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Export the tagged version into a tarfile. Note that this command
generates a gzipped tarfile directly from the repository:
<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:
<blockquote><tt>
cd ~/base<br />
bzr export
--root=base-3.15.5
-r tag:R3.15.5
base-3.15.5.tar.gz
mirror-3.15
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
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.15.5.tar.gz
gpg --armor --sign --detach-sig base-3.16.1.tar.gz
</tt></blockquote>
</td>
</tr>
@@ -305,14 +306,24 @@ relevent roles unless the Release Manager designates otherwise:</p>
<td>Test the tar file by extracting its contents and building it on at
least one supported platform</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Upload the release tar file to the Launchpad download area.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Find all Launchpad bug reports with the status Fix Committed which
have been fixed in this release and mark them Fix Released.</td>
</tr>
<tr>
<th colspan="3">Publish and Announce it</th>
</tr>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>If necessary recreate the tarfile following the instructions above.
Copy the tar file and its <tt>.asc</tt> signature file to the Base
<td>Copy the tar file and its <tt>.asc</tt> signature file to the Base
download area of the website.</td>
</tr>
<tr>
@@ -343,24 +354,13 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>Upload the release tar file to the Launchpad download area.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>Find all Launchpad bug reports with the status Fix Committed which
have been fixed in this release and mark them Fix Released.</td>
<td>Add an entry to the website News page, linking to the new version
webpage.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Email tech-talk</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>Add an entry to the website News page, linking to the new version
webpage.</td>
<td>Announce the release on the tech-talk mailing list.</td>
</tr>
</tbody>
</table>

View File

@@ -314,11 +314,21 @@ is used.</p>
<td>i &gt;= 16384</td>
<td>16384</td>
</tr>
<tr>
<td>EPICS_CA_AUTO_ARRAY_BYTES</td>
<td>i &gt;= YES</td>
<td>YES</td>
</tr>
<tr>
<td>EPICS_CA_MAX_SEARCH_PERIOD</td>
<td>r &gt; 60 seconds</td>
<td>300</td>
</tr>
<tr>
<td>EPICS_CA_MCAST_TTL</td>
<td>r &gt; 1</td>
<td>1</td>
</tr>
<tr>
<td>EPICS_TS_MIN_WEST</td>
<td>-720 &lt; i &lt;720 minutes</td>
@@ -754,6 +764,11 @@ buffers that are used for ordinary communication. If EPICS_CA_MAX_ARRAY_BYTES
is larger than 16384 then a second free list of larger data buffers is
established and used only after a client send its first large array request.</p>
<p>Beginning with R3.16.1, EPICS_CA_AUTO_ARRAY_BYTES=YES (the default) will ignore
EPICS_CA_MAX_ARRAY_BYTES and attempt to allocate sufficient buffer space
as needed. Setting EPICS_CA_AUTO_ARRAY_BYTES=NO will continue to respect
EPICS_CA_MAX_ARRAY_BYTES.</p>
<p>The CA client library uses EPICS_CA_MAX_ARRAY_BYTES to determines the
maximum array that it will send or receive. Likewise, the CA server uses
EPICS_CA_MAX_ARRAY_BYTES to determine the maximum array that it may send or
@@ -1146,16 +1161,10 @@ the output.</p>
<td>Wide mode "name timestamp value stat sevr" (read PVs as
DBR_TIME_xxx)</td>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM values as number (default are enum strings)</td>
</tr>
<tr>
<td>-d &lt;type&gt;</td>
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)
<p>or number of one of the following types:</p>
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)<br>
or number of one of the following types:<br>
<table border="1">
<tbody>
<tr>
@@ -1272,6 +1281,14 @@ the output.</p>
</table>
</td>
</tr>
<tr>
<td></td>
<td><strong>Enum format:</strong></td>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM value as number (default is enum string)</td>
</tr>
<tr>
<td></td>
<td><strong>Arrays:</strong></td>
@@ -1303,15 +1320,15 @@ the output.</p>
</tr>
<tr>
<td>-e &lt;nr&gt;</td>
<td>Use %e format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %e format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-f &lt;nr&gt;</td>
<td>Use %f format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %f format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-g &lt;nr&gt;</td>
<td>Use %g format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %g format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-s</td>
@@ -1349,6 +1366,14 @@ the output.</p>
<td>-0b</td>
<td>Print as binary number</td>
</tr>
<tr>
<td></td>
<td><strong>Alternate output field separator:</strong></td>
</tr>
<tr>
<td>-F &lt;ofs&gt;</td>
<td>Use &lt;ofs&gt; as an alternate output field separator</td>
</tr>
</tbody>
</table>
@@ -1381,9 +1406,10 @@ the output.</p>
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
</tr>
<tr>
<td>-m &lt;mask&gt;</td>
<td>Specify CA event mask to use, with &lt;mask&gt; being any combination
of 'v' (value), 'a' (alarm), 'l' (log), 'p' (property). Default: va</td>
<td>-m &lt;msk&gt;</td>
<td>Specify CA event mask to use. &lt;msk&gt; is any combination of<br>
'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property).<br>
Default event mask is 'va'</td>
</tr>
<tr>
<td>-p &lt;prio&gt;</td>
@@ -1405,8 +1431,8 @@ the output.</p>
'n' = no timestamps<br>
'r' = relative timestamps (time elapsed since start of program)<br>
'i' = incremental timestamps (time elapsed since last update)<br>
'I' = incremental timestamps (time elapsed since last update, by
channel)</td>
'I' = incremental timestamps (time since last update, by channel)<br>
'r', 'i' or 'I' require 's' or 'c' to select the time source</td>
</tr>
<tr>
<td></td>
@@ -1414,7 +1440,7 @@ the output.</p>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM values as number (default are enum strings)</td>
<td>Print DBF_ENUM values as number (default is enum string)</td>
</tr>
<tr>
<td></td>
@@ -1422,16 +1448,15 @@ the output.</p>
</tr>
<tr>
<td></td>
<td>Value format: Print number of requested values, then list of
values</td>
<td>Array values: Print number of elements, then list of values</td>
</tr>
<tr>
<td>Default:</td>
<td>Print all values</td>
<td>Default: Request and print all elements (dynamic arrays supported)</td>
</tr>
<tr>
<td>-# &lt;count&gt;</td>
<td>Print first &lt;count&gt; elements of an array</td>
<td>-# &lt;num&gt;</td>
<td>Request and print up to &lt;num&gt; elements</td>
</tr>
<tr>
<td>-S</td>
@@ -1439,23 +1464,23 @@ the output.</p>
</tr>
<tr>
<td></td>
<td><strong>Floating point type format:</strong></td>
<td><strong>Floating point format:</strong></td>
</tr>
<tr>
<td>Default:</td>
<td>Use %g format</td>
</tr>
<tr>
<td>-e &lt;nr&gt;</td>
<td>Use %e format, with &lt;nr&gt; digits after the decimal point</td>
<td>-e &lt;num&gt;</td>
<td>Use %e format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-f &lt;nr&gt;</td>
<td>Use %f format, with &lt;nr&gt; digits after the decimal point</td>
<td>-f &lt;num&gt;</td>
<td>Use %f format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-g &lt;nr&gt;</td>
<td>Use %g format, with &lt;nr&gt; digits after the decimal point</td>
<td>-g &lt;num&gt;</td>
<td>Use %g format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-s</td>
@@ -1497,21 +1522,27 @@ the output.</p>
</table>
<h3><a name="caput">caput</a></h3>
<pre>caput [options] &lt;PV name&gt; &lt;value&gt;
<pre>caput [options] &lt;PV name&gt; &lt;value&gt; ...
caput -a [options] &lt;PV name&gt; &lt;no of elements&gt; &lt;value&gt; ...</pre>
<h4>Description</h4>
<p>Put value to a PV.</p>
<p>The specified value is written to the PV (as a string). The PV value is read
before and after the write operation and printed as "Old" and "new" values on
stdout.</p>
<p>The specified value is written to the PV (as a string). The PV's value is
read before and after the write operation and printed as "Old" and "New" values
on stdout.</p>
<p>The array variant writes an array to the specified PV. The first numeric
argument specifying the number of array elements is kept for compatibility with
the array data format of caget - the actual number of values specified on the
command line is used.</p>
<p>There are two variants to the arguments for this command. For the scalar
variant without the <code>-a</code> flag, all the value arguments provided after
the PV name are concatenated with a single space character between them, and the
resulting string (up to 40 characters long unless the <code>-S</code> flag is
given) is written to the specified PV.</p>
<p>The array variant with the <code>-a</code> flag writes an array of string
values to the specified PV. The numeric argument giving the number of array
elements is actually ignored, the array length to be written is actually
controlled by the number of values provided on the command line.</p>
<table border="1">
<caption></caption>
@@ -1550,12 +1581,16 @@ command line is used.</p>
<td>-t</td>
<td>Terse mode - print only successfully written value, without name</td>
</tr>
<tr>
<td>-l</td>
<td>Long mode "name timestamp value stat sevr" (read PVs as DBR_TIME_xxx)</td>
</tr>
<tr>
<td></td>
<td><strong>Enum Format:</strong></td>
</tr>
<tr>
<td></td>
<td>Default:</td>
<td>Auto - try value as ENUM string, then as index number</td>
</tr>
<tr>
@@ -1571,17 +1606,24 @@ command line is used.</p>
<td><strong>Arrays:</strong></td>
</tr>
<tr>
<td>-a</td>
<td>Put array data</td>
<td>Default:</td>
<td>Put scalar</td>
</tr>
<tr>
<td></td>
<td>Value format: Print number of requested values, then list of
values</td>
<td>Value format: all value arguments concatenated with spaces</td>
</tr>
<tr>
<td>-S</td>
<td>Put string as an array of char (long string)</td>
<td>Put string as an array of chars (long string)</td>
</tr>
<tr>
<td>-a</td>
<td>Put array</td>
</tr>
<tr>
<td></td>
<td>Value format: number of values, then list of values</td>
</tr>
</tbody>
</table>

View File

@@ -69,7 +69,6 @@ LIBSRCS += comQueSend.cpp
LIBSRCS += comBuf.cpp
LIBSRCS += hostNameCache.cpp
LIBSRCS += msgForMultiplyDefinedPV.cpp
LIBSRCS_vxWorks += templateInstances.cpp
LIBRARY=ca

View File

@@ -1,94 +0,0 @@
/*************************************************************************\
* 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

@@ -28,7 +28,8 @@
#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_MINIMUM_SUPPORTED_VERSION 4u
# define CA_VSUPPORTED(MINOR) ((MINOR)>=CA_MINIMUM_SUPPORTED_VERSION)
# define CA_V41(MINOR) ((MINOR)>=1u)
# define CA_V42(MINOR) ((MINOR)>=2u)
# define CA_V43(MINOR) ((MINOR)>=3u)
@@ -42,35 +43,6 @@
# 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

View File

@@ -159,7 +159,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
this->localPort = htons ( tmpAddr.ia.sin_port );
}
epics_auto_ptr < CallbackGuard > pCBGuard;
std::auto_ptr < CallbackGuard > pCBGuard;
if ( ! enablePreemptiveCallback ) {
pCBGuard.reset ( new CallbackGuard ( this->cbMutex ) );
}

View File

@@ -32,6 +32,7 @@
#include "envDefs.h"
#include "locationException.h"
#include "errlog.h"
#include "epicsExport.h"
#define epicsExportSharedSymbols
#include "addrList.h"
@@ -218,9 +219,15 @@ cac::cac (
throw std::bad_alloc ();
}
freeListInitPvt ( &this->tcpLargeRecvBufFreeList, this->maxRecvBytesTCP, 1 );
if ( ! this->tcpLargeRecvBufFreeList ) {
throw std::bad_alloc ();
int autoMaxBytes;
if(envGetBoolConfigParam(&EPICS_CA_AUTO_ARRAY_BYTES, &autoMaxBytes))
autoMaxBytes = 1;
if(!autoMaxBytes) {
freeListInitPvt ( &this->tcpLargeRecvBufFreeList, this->maxRecvBytesTCP, 1 );
if ( ! this->tcpLargeRecvBufFreeList ) {
throw std::bad_alloc ();
}
}
unsigned bufsPerArray = this->maxRecvBytesTCP / comBuf::capacityBytes ();
if ( bufsPerArray > 1u ) {
@@ -231,9 +238,7 @@ cac::cac (
catch ( ... ) {
osiSockRelease ();
delete [] this->pUserName;
if ( this->tcpSmallRecvBufFreeList ) {
freeListCleanup ( this->tcpSmallRecvBufFreeList );
}
freeListCleanup ( this->tcpSmallRecvBufFreeList );
if ( this->tcpLargeRecvBufFreeList ) {
freeListCleanup ( this->tcpLargeRecvBufFreeList );
}
@@ -260,9 +265,14 @@ cac::cac (
tcpiiu * piiu = NULL;
SearchDestTCP * pdst = new SearchDestTCP ( *this, pNode->addr );
this->registerSearchDest ( guard, * pdst );
/* Initially assume that servers listed in EPICS_CA_NAME_SERVERS support at least minor
* version 11. This causes tcpiiu to send the user and host name authentication
* messages. When the actual Version message is received from the server it will
* be overwrite this assumption.
*/
bool newIIU = findOrCreateVirtCircuit (
guard, pNode->addr, cacChannel::priorityDefault,
piiu, CA_UKN_MINOR_VERSION, pdst );
piiu, 11, pdst );
free ( pNode );
if ( newIIU ) {
piiu->start ( guard );
@@ -318,7 +328,9 @@ cac::~cac ()
}
freeListCleanup ( this->tcpSmallRecvBufFreeList );
freeListCleanup ( this->tcpLargeRecvBufFreeList );
if ( this->tcpLargeRecvBufFreeList ) {
freeListCleanup ( this->tcpLargeRecvBufFreeList );
}
delete [] this->pUserName;
@@ -635,11 +647,13 @@ void cac::transferChanToVirtCircuit (
// must occur before moving to new iiu
pChan->getPIIU(guard)->uninstallChanDueToSuccessfulSearchResponse (
guard, *pChan, currentTime );
piiu->installChannel (
guard, *pChan, sid, typeCode, count );
if ( piiu ) {
piiu->installChannel (
guard, *pChan, sid, typeCode, count );
if ( newIIU ) {
piiu->start ( guard );
if ( newIIU ) {
piiu->start ( guard );
}
}
}
@@ -1304,9 +1318,11 @@ void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
callbackManager mgr ( this->notify, this->cbMutex );
epicsGuard < epicsMutex > guard ( this->mutex );
this->exception ( mgr.cbGuard, guard, ECA_DBLCHNL, buf, __FILE__, __LINE__ );
// remove from the list under lock
this->msgMultiPVList.remove ( mfmdpv );
}
// remove from the list and delete msg object
this->msgMultiPVList.remove ( mfmdpv );
// delete msg object
mfmdpv.~msgForMultiplyDefinedPV ();
this->mdpvFreeList.release ( & mfmdpv );
}

View File

@@ -51,6 +51,7 @@
class netWriteNotifyIO;
class netReadNotifyIO;
class netSubscription;
class tcpiiu;
// used to control access to cac's recycle routines which
// should only be indirectly invoked by CAC when its lock
@@ -193,12 +194,6 @@ public:
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
@@ -355,6 +350,8 @@ private:
cac ( const cac & );
cac & operator = ( const cac & );
friend class tcpiiu;
};
inline const char * cac::userNamePointer () const
@@ -385,35 +382,6 @@ 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
{

View File

@@ -24,7 +24,7 @@
DBE_ARCHIVE (DBE_LOG)
Trigger an event when an archive significant change in the channel's
valuue occurs. Relies on the archiver monitor deadband field under DCT.
value occurs. Relies on the archiver monitor deadband field under DCT.
DBE_ALARM
Trigger an event when the alarm state changes

View File

@@ -58,6 +58,7 @@ protected:
channelNode ();
bool isInstalledInServer ( epicsGuard < epicsMutex > & ) const;
bool isConnected ( epicsGuard < epicsMutex > & ) const;
public:
static unsigned getMaxSearchTimerCount ();
private:
enum channelState {

View File

@@ -26,13 +26,14 @@
#ifndef oldAccessh
#define oldAccessh
#include <memory>
#ifdef epicsExportSharedSymbols
# define oldAccessh_restore_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include "tsFreeList.h"
#include "epicsMemory.h"
#include "compilerDependencies.h"
#include "osiSock.h"
@@ -402,8 +403,8 @@ private:
epicsEvent ioDone;
epicsEvent callbackThreadActivityComplete;
epicsThreadId createdByThread;
epics_auto_ptr < CallbackGuard > pCallbackGuard;
epics_auto_ptr < cacContext > pServiceContext;
std::auto_ptr < CallbackGuard > pCallbackGuard;
std::auto_ptr < cacContext > pServiceContext;
caExceptionHandler * ca_exception_func;
void * ca_exception_arg;
caPrintfFunc * pVPrintfFunc;

View File

@@ -20,13 +20,16 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:ac:d:e:f:F:g:hnsStw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "caget.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('caget -h' gives help.)\n"
die "No pv name specified. ('caget.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "caget.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval { CA->pend_io($opt_w); };
if ($@) {

View File

@@ -16,10 +16,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('hw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('cainfo -h' gives help.)\n"
die "No pv name specified. ('cainfo.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "cainfo.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval {
CA->pend_io($opt_w);

View File

@@ -20,14 +20,17 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:c:e:f:F:g:hm:nsSw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "camonitor.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('camonitor -h' gives help.)\n"
die "No pv name specified. ('camonitor.pl -h' gives help.)\n"
unless @ARGV;
my %monitors;
my @chans = map { CA->new($_, \&conn_callback); } @ARGV;
my @chans = map { CA->new($_, \&conn_callback); } grep { $_ ne '' } @ARGV;
die "camonitor.pl: Please provide at least one non-empty pv name\n"
unless @chans;
my $fmt = ($opt_F eq ' ') ? "%-30s %s\n" : "%s$opt_F%s\n";

View File

@@ -17,11 +17,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('achlnsStw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('caput -h' gives help.)\n"
die "No pv name specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $pv = shift;
die "caput.pl: Empty pv name given.\n"
unless $pv ne '';
die "No value specified. ('caput -h' gives help.)\n"
die "No value specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $chan = CA->new($pv);

View File

@@ -504,6 +504,7 @@ void ca_repeater ()
if ( sockerrno == SOCK_EADDRINUSE ) {
osiSockRelease ();
debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) );
delete [] pBuf;
return;
}
char sockErrBuf[64];

View File

@@ -66,6 +66,8 @@ void repeaterSubscribeTimer::shutdown (
epicsTimerNotify::expireStatus repeaterSubscribeTimer::
expire ( const epicsTime & /* currentTime */ )
{
epicsGuard < epicsMutex > guard ( this->stateMutex );
static const unsigned nTriesToMsg = 50;
if ( this->attempts > nTriesToMsg && ! this->once ) {
callbackManager mgr ( this->ctxNotify, this->cbMutex );
@@ -92,12 +94,15 @@ epicsTimerNotify::expireStatus repeaterSubscribeTimer::
void repeaterSubscribeTimer::show ( unsigned /* level */ ) const
{
epicsGuard < epicsMutex > guard ( this->stateMutex );
::printf ( "repeater subscribe timer: attempts=%u registered=%u once=%u\n",
this->attempts, this->registered, this->once );
}
void repeaterSubscribeTimer::confirmNotify ()
{
epicsGuard < epicsMutex > guard ( this->stateMutex );
this->registered = true;
}

View File

@@ -70,6 +70,7 @@ private:
repeaterTimerNotify & iiu;
epicsMutex & cbMutex;
cacContextNotify & ctxNotify;
mutable epicsMutex stateMutex;
unsigned attempts;
bool registered;
bool once;

View File

@@ -24,7 +24,6 @@
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "tsMinMax.h"
#include "envDefs.h"
#define epicsExportSharedSymbols

View File

@@ -26,6 +26,9 @@
#include <stdexcept>
#include <string>
#include <stdlib.h>
#include "errlog.h"
#define epicsExportSharedSymbols
@@ -687,7 +690,7 @@ tcpiiu::tcpiiu (
curDataBytes ( 0ul ),
comBufMemMgr ( comBufMemMgrIn ),
cacRef ( cac ),
pCurData ( cac.allocateSmallBufferTCP () ),
pCurData ( (char*) freeListMalloc(this->cacRef.tcpSmallRecvBufFreeList) ),
pSearchDest ( pSearchDestIn ),
mutex ( mutexIn ),
cbMutex ( cbMutexIn ),
@@ -711,9 +714,12 @@ tcpiiu::tcpiiu (
socketHasBeenClosed ( false ),
unresponsiveCircuit ( false )
{
if(!pCurData)
throw std::bad_alloc();
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( this->sock == INVALID_SOCKET ) {
cac.releaseSmallBufferTCP ( this->pCurData );
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData);
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
@@ -1023,11 +1029,14 @@ tcpiiu :: ~tcpiiu ()
// free message body cache
if ( this->pCurData ) {
if ( this->curDataMax == MAX_TCP ) {
this->cacRef.releaseSmallBufferTCP ( this->pCurData );
if ( this->curDataMax <= MAX_TCP ) {
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData);
}
else if ( this->cacRef.tcpLargeRecvBufFreeList ) {
freeListFree(this->cacRef.tcpLargeRecvBufFreeList, this->pCurData);
}
else {
this->cacRef.releaseLargeBufferTCP ( this->pCurData );
free ( this->pCurData );
}
}
}
@@ -1197,18 +1206,46 @@ bool tcpiiu::processIncoming (
// make sure we have a large enough message body cache
//
if ( this->curMsg.m_postsize > this->curDataMax ) {
if ( this->curDataMax == MAX_TCP &&
this->cacRef.largeBufferSizeTCP() >= this->curMsg.m_postsize ) {
char * pBuf = this->cacRef.allocateLargeBufferTCP ();
if ( pBuf ) {
this->cacRef.releaseSmallBufferTCP ( this->pCurData );
this->pCurData = pBuf;
this->curDataMax = this->cacRef.largeBufferSizeTCP ();
assert (this->curMsg.m_postsize > MAX_TCP);
char * newbuf = NULL;
arrayElementCount newsize;
if ( !this->cacRef.tcpLargeRecvBufFreeList ) {
// round size up to multiple of 4K
newsize = ((this->curMsg.m_postsize-1)|0xfff)+1;
if ( this->curDataMax <= MAX_TCP ) {
// small -> large
newbuf = (char*)malloc(newsize);
} else {
// expand large to larger
newbuf = (char*)realloc(this->pCurData, newsize);
}
else {
this->printFormated ( mgr.cbGuard,
"CAC: not enough memory for message body cache (ignoring response message)\n");
} else if ( this->curMsg.m_postsize <= this->cacRef.maxRecvBytesTCP ) {
newbuf = (char*) freeListMalloc(this->cacRef.tcpLargeRecvBufFreeList);
newsize = this->cacRef.maxRecvBytesTCP;
}
if ( newbuf) {
if (this->curDataMax <= MAX_TCP) {
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData );
} else if (this->cacRef.tcpLargeRecvBufFreeList) {
freeListFree(this->cacRef.tcpLargeRecvBufFreeList, this->pCurData );
} else {
// called realloc()
}
this->pCurData = newbuf;
this->curDataMax = newsize;
} else {
this->printFormated ( mgr.cbGuard,
"CAC: not enough memory for message body cache (ignoring response message)\n");
}
}
@@ -1426,7 +1463,7 @@ void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard,
}
arrayElementCount maxBytes;
if ( CA_V49 ( this->minorProtocolVersion ) ) {
maxBytes = this->cacRef.largeBufferSizeTCP ();
maxBytes = 0xfffffff0;
}
else {
maxBytes = MAX_TCP;
@@ -1537,7 +1574,7 @@ void tcpiiu::subscriptionRequest (
guard, CA_V413(this->minorProtocolVersion) );
arrayElementCount maxBytes;
if ( CA_V49 ( this->minorProtocolVersion ) ) {
maxBytes = this->cacRef.largeBufferSizeTCP ();
maxBytes = 0xfffffff0;
}
else {
maxBytes = MAX_TCP;
@@ -1584,7 +1621,7 @@ void tcpiiu::subscriptionUpdateRequest (
guard, CA_V413(this->minorProtocolVersion) );
arrayElementCount maxBytes;
if ( CA_V49 ( this->minorProtocolVersion ) ) {
maxBytes = this->cacRef.largeBufferSizeTCP ();
maxBytes = 0xfffffff0;
}
else {
maxBytes = MAX_TCP;

View File

@@ -1,89 +0,0 @@
/*************************************************************************\
* 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
*/
#define epicsExportSharedSymbols
#include "virtualCircuit.h"
#include "bhe.h"
#include "cac.h"
#include "syncGroup.h"
#include "nciu.h"
#include "udpiiu.h"
#include "oldAccess.h"
#include "msgForMultiplyDefinedPV.h"
#include "repeaterClient.h"
#include "hostNameCache.h"
#include "comBuf.h"
#ifdef _MSC_VER
# pragma warning ( push )
# pragma warning ( disable:4660 )
#endif
template class resTable < nciu, chronIntId >;
template class chronIntIdResTable < nciu >;
template class resTable < baseNMIU, chronIntId >;
template class chronIntIdResTable < baseNMIU >;
template class resTable < CASG, chronIntId >;
template class chronIntIdResTable < CASG >;
template class resTable < bhe, inetAddrID >;
template class resTable < tcpiiu, caServerID >;
template class tsFreeList < bhe, 0x100 >;
template class tsFreeList < tcpiiu, 32, epicsMutexNOOP >;
template class tsFreeList < netReadNotifyIO, 1024, epicsMutexNOOP >;
template class tsFreeList < netWriteNotifyIO, 1024, epicsMutexNOOP >;
template class tsFreeList < netSubscription, 1024, epicsMutexNOOP >;
template class tsFreeList < CASG, 128, epicsMutexNOOP >;
template class tsFreeList < syncGroupReadNotify, 128, epicsMutexNOOP >;
template class tsFreeList < syncGroupWriteNotify, 128, epicsMutexNOOP >;
template class tsFreeList < comBuf, 0x20 >;
template class tsFreeList < getCallback, 1024, epicsMutexNOOP >;
template class tsFreeList < getCopy, 1024, epicsMutexNOOP >;
template class tsFreeList < msgForMultiplyDefinedPV, 16 >;
template class tsFreeList < nciu, 1024, epicsMutexNOOP>;
template class tsFreeList < oldChannelNotify, 1024, epicsMutexNOOP >;
template class tsFreeList < oldSubscription, 1024, epicsMutexNOOP >;
template class tsFreeList < putCallback, 1024, epicsMutexNOOP >;
template class tsFreeList < repeaterClient, 0x20 >;
template class epicsSingleton < localHostName >;
template class epics_auto_ptr < epics_auto_ptr < class searchTimer >, eapt_array >;
template unsigned comBuf :: push ( const double * pValue, unsigned nElem );
template unsigned comBuf :: push ( const float * pValue, unsigned nElem );
template unsigned comBuf :: push ( const int * pValue, unsigned nElem );
template unsigned comBuf :: push ( const short * pValue, unsigned nElem );
template comBuf :: popStatus comBuf :: pop ( unsigned int & returnVal );
template comBuf :: popStatus comBuf :: pop ( unsigned short & returnVal );
template comBuf :: popStatus comBuf :: pop ( unsigned char & returnVal );
template void WireSet ( float const &, unsigned char * );
template void WireSet ( int const &, unsigned char * );
template void WireSet ( short const &, unsigned char * );
template void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO
(epicsGuard < epicsMutex > &, syncGroupWriteNotify & );
template void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO
( epicsGuard < epicsMutex > &, syncGroupReadNotify & );
#ifdef _MSC_VER
# pragma warning ( pop )
#endif

View File

@@ -541,11 +541,11 @@ int main (int argc, char *argv[])
for (n = 0; optind < argc; n++, optind++)
pvs[n].name = argv[optind] ; /* Copy PV names from command line */
connect_pvs(pvs, nPvs);
result = connect_pvs(pvs, nPvs);
/* Read and print data */
result = caget(pvs, nPvs, request, format, type, count);
if (!result)
result = caget(pvs, nPvs, request, format, type, count);
/* Shut down Channel Access */
ca_context_destroy();

View File

@@ -211,10 +211,11 @@ int main (int argc, char *argv[])
for (n = 0; optind < argc; n++, optind++)
pvs[n].name = argv[optind] ; /* Copy PV names from command line */
connect_pvs(pvs, nPvs);
result = connect_pvs(pvs, nPvs);
/* Print data */
result = cainfo(pvs, nPvs);
if (!result)
result = cainfo(pvs, nPvs);
/* Shut down Channel Access */
ca_context_destroy();

View File

@@ -56,7 +56,7 @@ static epicsEventId epId;
void usage (void)
{
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value>\n"
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value> ...\n"
" caput -a [options] <PV name> <no of values> <PV value> ...\n\n"
" -h: Help: Print this message\n"
"Channel Access options:\n"
@@ -71,9 +71,11 @@ void usage (void)
" -n: Force interpretation of values as numbers\n"
" -s: Force interpretation of values as strings\n"
"Arrays:\n"
" Default: Put scalar\n"
" Value format: all value arguments concatenated with spaces\n"
" -S: Put string as an array of chars (long string)\n"
" -a: Put array\n"
" Value format: number of requested values, then list of values\n"
" -S: Put string as an array of char (long string)\n"
" Value format: number of values, then list of values\n"
"Alternate output field separator:\n"
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
"\nExample: caput my_channel 1.2\n"

View File

@@ -64,6 +64,52 @@ const udpiiu::pProtoStubUDP udpiiu::udpJumpTableCAC [] =
&udpiiu::repeaterAckAction,
};
static
double getMaxPeriod()
{
double maxPeriod = maxSearchPeriodDefault;
if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) {
long longStatus = envGetDoubleConfigParam (
& EPICS_CA_MAX_SEARCH_PERIOD, & maxPeriod );
if ( ! longStatus ) {
if ( maxPeriod < maxSearchPeriodLowerLimit ) {
epicsPrintf ( "\"%s\" out of range (low)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
maxPeriod = maxSearchPeriodLowerLimit;
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, maxPeriod );
}
}
else {
epicsPrintf ( "EPICS \"%s\" wasnt a real number\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, maxPeriod );
}
}
return maxPeriod;
}
static
unsigned getNTimers(double maxPeriod)
{
unsigned nTimers = static_cast < unsigned > ( 1.0 + log ( maxPeriod / minRoundTripEstimate ) / log ( 2.0 ) );
if ( nTimers > channelNode::getMaxSearchTimerCount () ) {
nTimers = channelNode::getMaxSearchTimerCount ();
epicsPrintf ( "\"%s\" out of range (high)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name,
(1<<(nTimers-1)) * minRoundTripEstimate );
}
return nTimers;
}
//
// udpiiu::udpiiu ()
//
@@ -85,14 +131,15 @@ udpiiu::udpiiu (
repeaterSubscribeTmr (
m_repeaterTimerNotify, timerQueue, cbMutexIn, ctxNotifyIn ),
govTmr ( *this, timerQueue, cacMutexIn ),
maxPeriod ( maxSearchPeriodDefault ),
maxPeriod ( getMaxPeriod() ),
rtteMean ( minRoundTripEstimate ),
rtteMeanDev ( 0 ),
cacRef ( cac ),
cbMutex ( cbMutexIn ),
cacMutex ( cacMutexIn ),
nTimers ( getNTimers(maxPeriod) ),
ppSearchTmr ( nTimers ),
nBytesInXmitBuf ( 0 ),
nTimers ( 0 ),
beaconAnomalyTimerIndex ( 0 ),
sequenceNumber ( 0 ),
lastReceivedSeqNo ( 0 ),
@@ -104,45 +151,13 @@ udpiiu::udpiiu (
lastReceivedSeqNoIsValid ( false )
{
cacGuard.assertIdenticalMutex ( cacMutex );
if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) {
long longStatus = envGetDoubleConfigParam (
& EPICS_CA_MAX_SEARCH_PERIOD, & this->maxPeriod );
if ( ! longStatus ) {
if ( this->maxPeriod < maxSearchPeriodLowerLimit ) {
epicsPrintf ( "\"%s\" out of range (low)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
this->maxPeriod = maxSearchPeriodLowerLimit;
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
}
}
else {
epicsPrintf ( "EPICS \"%s\" wasnt a real number\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
}
}
double powerOfTwo = log ( this->maxPeriod / minRoundTripEstimate ) / log ( 2.0 );
this->nTimers = static_cast < unsigned > ( powerOfTwo + 1.0 );
if ( this->nTimers > channelNode::getMaxSearchTimerCount () ) {
this->nTimers = channelNode::getMaxSearchTimerCount ();
epicsPrintf ( "\"%s\" out of range (high)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name,
(1<<(this->nTimers-1)) * minRoundTripEstimate );
}
powerOfTwo = log ( beaconAnomalySearchPeriod / minRoundTripEstimate ) / log ( 2.0 );
double powerOfTwo = log ( beaconAnomalySearchPeriod / minRoundTripEstimate ) / log ( 2.0 );
this->beaconAnomalyTimerIndex = static_cast < unsigned > ( powerOfTwo + 1.0 );
if ( this->beaconAnomalyTimerIndex >= this->nTimers ) {
this->beaconAnomalyTimerIndex = this->nTimers - 1;
}
this->ppSearchTmr.reset ( new epics_auto_ptr < class searchTimer > [ this->nTimers ] );
for ( unsigned i = 0; i < this->nTimers; i++ ) {
this->ppSearchTmr[i].reset (
new searchTimer ( *this, timerQueue, i, cacMutexIn,
@@ -176,6 +191,22 @@ udpiiu::udpiiu (
}
#endif
#ifdef IP_MULTICAST_TTL
{
int ttl;
long val;
if(envGetLongConfigParam(&EPICS_CA_MCAST_TTL, &val))
val =1;
ttl = val;
if ( setsockopt(this->sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl))) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf("CAC: failed to set mcast ttl %d\n", ttl);
}
}
#endif
int boolValue = true;
int status = setsockopt ( this->sock, SOL_SOCKET, SO_BROADCAST,
(char *) &boolValue, sizeof ( boolValue ) );
@@ -915,10 +946,12 @@ bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard,
caHdr * pbufmsg = ( caHdr * ) &this->xmitBuf[this->nBytesInXmitBuf];
*pbufmsg = msg;
memcpy ( pbufmsg + 1, pExt, extsize );
if ( extsize != alignedExtSize ) {
char *pDest = (char *) ( pbufmsg + 1 );
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
if ( extsize ) {
memcpy ( pbufmsg + 1, pExt, extsize );
if ( extsize != alignedExtSize ) {
char *pDest = (char *) ( pbufmsg + 1 );
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
}
}
AlignedWireRef < epicsUInt16 > ( pbufmsg->m_postsize ) = alignedExtSize;
this->nBytesInXmitBuf += msgsize;

View File

@@ -25,6 +25,8 @@
#ifndef udpiiuh
#define udpiiuh
#include <memory>
#ifdef epicsExportSharedSymbols
# define udpiiuh_accessh_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
@@ -32,9 +34,7 @@
#include "osiSock.h"
#include "epicsThread.h"
#include "epicsMemory.h"
#include "epicsTime.h"
#include "tsMinMax.h"
#include "tsDLList.h"
#ifdef udpiiuh_accessh_epicsExportSharedSymbols
@@ -160,15 +160,24 @@ private:
repeaterSubscribeTimer repeaterSubscribeTmr;
disconnectGovernorTimer govTmr;
tsDLList < SearchDest > _searchDestList;
double maxPeriod;
const double maxPeriod;
double rtteMean;
double rtteMeanDev;
cac & cacRef;
epicsMutex & cbMutex;
epicsMutex & cacMutex;
epics_auto_ptr < epics_auto_ptr < class searchTimer >, eapt_array > ppSearchTmr;
const unsigned nTimers;
struct SearchArray {
typedef std::auto_ptr <searchTimer> value_type;
value_type *arr;
SearchArray(size_t n) : arr(new value_type[n]) {}
~SearchArray() { delete[] arr; }
value_type& operator[](size_t i) const { return arr[i]; }
private:
SearchArray(const SearchArray&);
SearchArray& operator=(const SearchArray&);
} ppSearchTmr;
unsigned nBytesInXmitBuf;
unsigned nTimers;
unsigned beaconAnomalyTimerIndex;
ca_uint32_t sequenceNumber;
ca_uint32_t lastReceivedSeqNo;

View File

@@ -25,9 +25,7 @@
#ifndef virtualCircuith
#define virtualCircuith
#include "epicsMemory.h"
#include "tsDLList.h"
#include "tsMinMax.h"
#include "comBuf.h"
#include "caServerID.h"

View File

@@ -308,7 +308,7 @@ void gdd::test()
pdd->convertOffsetsToAddress();
pdd->dump();
pdd->unreference();
delete buf;
delete [] buf;
}
#endif
@@ -510,7 +510,7 @@ void gddContainer::test(void)
fprintf(stderr,"=====RE-DUMP OF ORIGINAL CONTAINER:\n");
dump();
cdd1->unreference();
delete buf;
delete [] buf;
// test copy(), Dup(), copyInfo()
fprintf(stderr,"=======CREATING TEST CONTAINER FOR *COPY* TEST:\n");

View File

@@ -53,7 +53,6 @@ LIBSRCS += outBuf.cc
LIBSRCS += casCtx.cc
LIBSRCS += casEventMask.cc
LIBSRCS += ioBlocked.cc
LIBSRCS += casBufferFactory.cc
LIBSRCS += pvExistReturn.cc
LIBSRCS += pvAttachReturn.cc
LIBSRCS += caNetAddr.cc
@@ -80,8 +79,6 @@ ifeq ($(VX_GNU_VERSION), 4.1.2)
casStreamOS_CXXFLAGS_vxWorks-ppc604 = -O0
endif
LIBSRCS_vxWorks += templateInstances.cpp
LIBRARY = cas
cas_LIBS = ca gdd Com
cas_SYS_LIBS_WIN32 = ws2_32

View File

@@ -13,7 +13,7 @@
//
#include "directoryServer.h"
#include "tsMinMax.h"
#include "epicsAlgorithm.h"
const pvInfo *pvInfo::pFirst;
@@ -128,7 +128,7 @@ pvExistReturn directoryServer::pvExistTest
}
else {
size_t diff = pLastStr-pPVName;
diff = tsMin (diff, sizeof(pvNameBuf)-1);
diff = epicsMin (diff, sizeof(pvNameBuf)-1);
memcpy (pvNameBuf, pPVName, diff);
pvNameBuf[diff] = '\0';
pLastStr = pvNameBuf;

View File

@@ -170,7 +170,7 @@ static int parseDirectoryFP (FILE *pf, const char *pFileName)
status = aToIPAddr (hostNameStr, 0u, &ipa);
if (status) {
fprintf (pf, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
fprintf (stderr, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
hostNameStr, pFileName, pvNameStr);
return -1;
}

View File

@@ -1,104 +0,0 @@
/*************************************************************************\
* 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
*/
#include <new>
#include "envDefs.h"
#include "freeList.h"
#include "errlog.h"
#define epicsExportSharedSymbols
#include "clientBufMemoryManager.h"
#include "caProto.h"
casBufferFactory::casBufferFactory () :
smallBufFreeList ( 0 ), largeBufFreeList ( 0 ), largeBufferSizePriv ( 0u )
{
long maxBytesAsALong;
long status = envGetLongConfigParam ( & EPICS_CA_MAX_ARRAY_BYTES, & maxBytesAsALong );
if ( status || maxBytesAsALong < 0 ) {
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" );
this->largeBufferSizePriv = MAX_TCP;
}
else {
/* allow room for the protocol header so that they get the array size they requested */
static const unsigned headerSize = sizeof ( caHdr ) + 2 * sizeof ( ca_uint32_t );
ca_uint32_t maxBytes = ( unsigned ) maxBytesAsALong;
if ( maxBytes < 0xffffffff - headerSize ) {
maxBytes += headerSize;
}
else {
maxBytes = 0xffffffff;
}
if ( maxBytes < MAX_TCP ) {
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP );
this->largeBufferSizePriv = MAX_TCP;
}
else {
this->largeBufferSizePriv = maxBytes;
}
}
freeListInitPvt ( & this->smallBufFreeList, MAX_MSG_SIZE, 8 );
freeListInitPvt ( & this->largeBufFreeList, this->largeBufferSizePriv, 1 );
}
casBufferFactory::~casBufferFactory ()
{
freeListCleanup ( this->smallBufFreeList );
freeListCleanup ( this->largeBufFreeList );
}
unsigned casBufferFactory::smallBufferSize () const
{
return MAX_MSG_SIZE;
}
char * casBufferFactory::newSmallBuffer ()
{
void * pBuf = freeListCalloc ( this->smallBufFreeList );
if ( ! pBuf ) {
throw std::bad_alloc();
}
return static_cast < char * > ( pBuf );
}
void casBufferFactory::destroySmallBuffer ( char * pBuf )
{
if ( pBuf ) {
freeListFree ( this->smallBufFreeList, pBuf );
}
}
unsigned casBufferFactory::largeBufferSize () const
{
return this->largeBufferSizePriv;
}
char * casBufferFactory::newLargeBuffer ()
{
void * pBuf = freeListCalloc ( this->largeBufFreeList );
if ( ! pBuf ) {
throw std::bad_alloc();
}
return static_cast < char * > ( pBuf );
}
void casBufferFactory::destroyLargeBuffer ( char * pBuf )
{
if ( pBuf ) {
freeListFree ( this->largeBufFreeList, pBuf );
}
}

View File

@@ -21,6 +21,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
casChannel & chanIn, casPVI & pvIn, ca_uint32_t cidIn ) :
privateForPV ( clientIn, *this ),
pv ( pvIn ),
maxElem( pvIn.nativeCount() ),
chan ( chanIn ),
cid ( cidIn ),
serverDeletePending ( false ),
@@ -29,7 +30,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
}
casChannelI::~casChannelI ()
{
{
this->privateForPV.client().removeFromEventQueue (
*this, this->accessRightsEvPending );
@@ -48,7 +49,7 @@ void casChannelI::uninstallFromPV ( casEventSys & eventSys )
this->privateForPV.removeSelfFromPV ( this->pv, dest );
while ( casMonitor * pMon = dest.get () ) {
eventSys.prepareMonitorForDestroy ( *pMon );
}
}
}
void casChannelI::show ( unsigned level ) const
@@ -68,13 +69,13 @@ caStatus casChannelI::cbFunc (
{
caStatus stat = S_cas_success;
{
stat = this->privateForPV.client().accessRightsResponse (
stat = this->privateForPV.client().accessRightsResponse (
clientGuard, this );
}
if ( stat == S_cas_success ) {
this->accessRightsEvPending = false;
}
return stat;
if ( stat == S_cas_success ) {
this->accessRightsEvPending = false;
}
return stat;
}
caStatus casChannelI::read ( const casCtx & ctx, gdd & prototype )

View File

@@ -1,4 +1,3 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
@@ -31,55 +30,62 @@ class casChannelI : public tsDLNode < casChannelI >,
public:
casChannelI ( casCoreClient & clientIn, casChannel & chanIn,
casPVI & pvIn, ca_uint32_t cidIn );
~casChannelI ();
~casChannelI ();
void casChannelDestroyFromInterfaceNotify ();
const caResId getCID ();
const caResId getSID ();
const caResId getCID ();
const caResId getSID ();
void uninstallFromPV ( casEventSys & eventSys );
void installIntoPV ();
void installIO ( casAsyncIOI & );
void uninstallIO ( casAsyncIOI & );
void installMonitor ( casMonitor & mon );
casMonitor * removeMonitor ( ca_uint32_t clientIdIn );
casPVI & getPVI () const;
void clearOutstandingReads ();
void postAccessRightsEvent ();
casPVI & getPVI () const;
void clearOutstandingReads ();
void postAccessRightsEvent ();
const gddEnumStringTable & enumStringTable () const;
void setOwner ( const char * const pUserName,
const char * const pHostName );
bool readAccess () const;
ca_uint32_t getMaxElem () const;
void setOwner ( const char * const pUserName,
const char * const pHostName );
bool readAccess () const;
bool writeAccess () const;
bool confirmationRequested () const;
bool confirmationRequested () const;
caStatus read ( const casCtx & ctx, gdd & prototype );
caStatus write ( const casCtx & ctx, const gdd & value );
caStatus writeNotify ( const casCtx & ctx, const gdd & value );
void show ( unsigned level ) const;
void show ( unsigned level ) const;
private:
chanIntfForPV privateForPV;
tsDLList < casAsyncIOI > ioList;
casPVI & pv;
tsDLList < casAsyncIOI > ioList;
casPVI & pv;
ca_uint32_t maxElem;
casChannel & chan;
caResId cid; // client id
caResId cid; // client id
bool serverDeletePending;
bool accessRightsEvPending;
//epicsShareFunc virtual void destroy ();
caStatus cbFunc (
bool accessRightsEvPending;
//epicsShareFunc virtual void destroy ();
caStatus cbFunc (
casCoreClient &,
epicsGuard < casClientMutex > &,
epicsGuard < evSysMutex > & );
void postDestroyEvent ();
casChannelI ( const casChannelI & );
casChannelI & operator = ( const casChannelI & );
casChannelI ( const casChannelI & );
casChannelI & operator = ( const casChannelI & );
};
inline casPVI & casChannelI::getPVI () const
{
return this->pv;
return this->pv;
}
inline ca_uint32_t casChannelI::getMaxElem () const
{
return this->maxElem;
}
inline const caResId casChannelI::getCID ()
{
return this->cid;
return this->cid;
}
inline const caResId casChannelI::getSID ()
@@ -89,7 +95,7 @@ inline const caResId casChannelI::getSID ()
inline void casChannelI::postAccessRightsEvent ()
{
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
}
inline const gddEnumStringTable & casChannelI::enumStringTable () const
@@ -108,7 +114,7 @@ inline void casChannelI::clearOutstandingReads ()
}
inline void casChannelI::setOwner ( const char * const pUserName,
const char * const pHostName )
const char * const pHostName )
{
this->chan.setOwner ( pUserName, pHostName );
}

View File

@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
@@ -24,39 +24,39 @@
casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
{
& casDGClient::versionAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::versionAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::searchAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::searchAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::echoAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction
};
//
@@ -64,9 +64,9 @@ casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
//
casDGClient::casDGClient ( caServerI & serverIn, clientBufMemoryManager & mgrIn ) :
casCoreClient ( serverIn ),
in ( *this, mgrIn, MAX_UDP_RECV + sizeof ( cadg ) ),
in ( *this, mgrIn, MAX_UDP_RECV + sizeof ( cadg ) ),
out ( *this, mgrIn ),
seqNoOfReq ( 0 ),
seqNoOfReq ( 0 ),
minor_version_number ( 0 )
{
}
@@ -84,7 +84,7 @@ casDGClient::~casDGClient()
//
void casDGClient::destroy()
{
printf("Attempt to destroy the DG client was ignored\n");
printf("Attempt to destroy the DG client was ignored\n");
}
//
@@ -92,16 +92,16 @@ void casDGClient::destroy()
//
void casDGClient::show (unsigned level) const
{
printf ( "casDGClient at %p\n",
static_cast <const void *> ( this ) );
if (level>=1u) {
char buf[64];
this->hostName (buf, sizeof(buf));
printf ("Client Host=%s\n", buf);
printf ( "casDGClient at %p\n",
static_cast <const void *> ( this ) );
if (level>=1u) {
char buf[64];
this->hostName (buf, sizeof(buf));
printf ("Client Host=%s\n", buf);
this->casCoreClient::show ( level - 1u );
this->in.show ( level - 1u );
this->out.show ( level - 1u );
}
}
}
//
@@ -109,15 +109,17 @@ void casDGClient::show (unsigned level) const
//
caStatus casDGClient::uknownMessageAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const caHdrLargeArray * mp = this->ctx.getMsg();
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
}
return S_cas_badProtocol;
return S_cas_badProtocol;
}
//
@@ -125,9 +127,19 @@ caStatus casDGClient::uknownMessageAction ()
//
caStatus casDGClient::searchAction()
{
const caHdrLargeArray *mp = this->ctx.getMsg();
const caHdrLargeArray *mp = this->ctx.getMsg();
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
caStatus status;
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\" but is too old\n",
pHostName, pChanName );
}
return S_cas_badProtocol;
}
//
// check the sanity of the message
@@ -135,7 +147,7 @@ caStatus casDGClient::searchAction()
if ( mp->m_postsize <= 1 ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"empty PV name extension in UDP search request?\n" );
return S_cas_success;
}
@@ -143,68 +155,68 @@ caStatus casDGClient::searchAction()
if ( pChanName[0] == '\0' ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"zero length PV name in UDP search request?\n" );
return S_cas_success;
}
// check for an unterminated string before calling server tool
// by searching backwards through the string (some early versions
// by searching backwards through the string (some early versions
// of the client library might not be setting the pad bytes to nill)
for ( unsigned i = mp->m_postsize-1; pChanName[i] != '\0'; i-- ) {
if ( i <= 1 ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"unterminated PV name in UDP search request?\n" );
return S_cas_success;
}
}
if ( this->getCAS().getDebugLevel() > 6u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\"\n",
if ( this->getCAS().getDebugLevel() > 6u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\"\n",
pHostName, pChanName );
}
}
//
// verify that we have sufficent memory for a PV and a
// monitor prior to calling PV exist test so that when
// the server runs out of memory we dont reply to
// search requests, and therefore dont thrash through
// caServer::pvExistTest() and casCreatePV::pvAttach()
//
//
// verify that we have sufficent memory for a PV and a
// monitor prior to calling PV exist test so that when
// the server runs out of memory we dont reply to
// search requests, and therefore dont thrash through
// caServer::pvExistTest() and casCreatePV::pvAttach()
//
if ( ! osiSufficentSpaceInPool ( 0 ) ) {
return S_cas_success;
}
//
// ask the server tool if this PV exists
//
this->userStartedAsyncIO = false;
pvExistReturn pver =
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
//
// ask the server tool if this PV exists
//
this->userStartedAsyncIO = false;
pvExistReturn pver =
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
//
// prevent problems when they initiate
// async IO but dont return status
// indicating so (and vise versa)
//
if ( this->userStartedAsyncIO ) {
//
// prevent problems when they initiate
// async IO but dont return status
// indicating so (and vise versa)
//
if ( this->userStartedAsyncIO ) {
if ( pver.getStatus() != pverAsyncCompletion ) {
errMessage (S_cas_badParameter,
"- assuming asynch IO status from caServer::pvExistTest()");
errMessage (S_cas_badParameter,
"- assuming asynch IO status from caServer::pvExistTest()");
}
status = S_cas_success;
}
else {
//
// otherwise we assume sync IO operation was initiated
//
}
else {
//
// otherwise we assume sync IO operation was initiated
//
switch ( pver.getStatus() ) {
case pverExistsHere:
status = this->searchResponse (*mp, pver);
status = this->searchResponse (*mp, pver);
break;
case pverDoesNotExistHere:
@@ -212,36 +224,36 @@ caStatus casDGClient::searchAction()
break;
case pverAsyncCompletion:
errMessage (S_cas_badParameter,
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
errMessage (S_cas_badParameter,
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
default:
errMessage (S_cas_badParameter,
"- invalid return from caServer::pvExistTest() ignored");
errMessage (S_cas_badParameter,
"- invalid return from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
}
}
}
}
return status;
}
//
// caStatus casDGClient::searchResponse()
//
caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
const pvExistReturn & retVal )
{
caStatus status;
if ( retVal.getStatus() != pverExistsHere ) {
return S_cas_success;
}
//
// starting with V4.1 the count field is used (abused)
// by the client to store the minor version number of
// by the client to store the minor version number of
// the client.
//
// Old versions expect alloc of channel in response
@@ -250,8 +262,8 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
if ( !CA_V44(msg.m_count) ) {
char pName[64u];
this->hostName (pName, sizeof (pName));
errlogPrintf (
"client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n",
errlogPrintf (
"client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n",
pName);
//
// old connect protocol was dropped when the
@@ -264,19 +276,19 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
}
//
// cid field is abused to carry the IP
// cid field is abused to carry the IP
// address in CA_V48 or higher
// (this allows a CA servers to serve
// as a directory service)
//
// data type field is abused to carry the IP
// data type field is abused to carry the IP
// port number here CA_V44 or higher
// (this allows multiple CA servers on one
// host)
//
ca_uint32_t serverAddr;
ca_uint16_t serverPort;
if ( CA_V48( msg.m_count ) ) {
if ( CA_V48( msg.m_count ) ) {
struct sockaddr_in ina;
if ( retVal.addrIsValid() ) {
caNetAddr addr = retVal.getAddr();
@@ -296,7 +308,7 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
ina = addr.getSockIP();
//
// We dont fill in the servers address here
// because the server was not bound to a particular
// because the server was not bound to a particular
// interface, and we would need to waste CPU performing
// the following steps to determine the interface that
// will be used:
@@ -318,31 +330,31 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
serverAddr = ~0U;
serverPort = ntohs ( inetAddr.sin_port );
}
ca_uint16_t * pMinorVersion;
epicsGuard < epicsMutex > guard ( this->mutex );
status = this->out.copyInHeader ( CA_PROTO_SEARCH,
sizeof ( *pMinorVersion ), serverPort, 0,
serverAddr, msg.m_available,
status = this->out.copyInHeader ( CA_PROTO_SEARCH,
sizeof ( *pMinorVersion ), serverPort, 0,
serverAddr, msg.m_available,
reinterpret_cast <void **> ( &pMinorVersion ) );
//
// Starting with CA V4.1 the minor version number
// is appended to the end of each search reply.
// This value is ignored by earlier clients.
// This value is ignored by earlier clients.
//
if ( status == S_cas_success ) {
AlignedWireRef < epicsUInt16 > tmp ( *pMinorVersion );
tmp = CA_MINOR_PROTOCOL_REVISION;
this->out.commitMsg ();
}
return status;
}
//
// casDGClient::searchFailResponse()
// (only when requested by the client
// - when it isnt a reply to a broadcast)
// casDGClient::searchFailResponse()
// (only when requested by the client
// - when it isnt a reply to a broadcast)
//
caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
{
@@ -350,9 +362,9 @@ caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 );
this->out.commitMsg ();
this->out.commitMsg ();
return S_cas_success;
return S_cas_success;
}
/*
@@ -360,8 +372,17 @@ caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
*/
caStatus casDGClient::versionAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const caHdrLargeArray * mp = this->ctx.getMsg();
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is too old\n",
pHostName );
}
return S_cas_badProtocol;
}
if ( mp->m_count != 0 ) {
this->minor_version_number = static_cast <ca_uint16_t> ( mp->m_count );
if ( CA_V411 ( mp->m_count ) ) {
@@ -371,7 +392,7 @@ caStatus casDGClient::versionAction ()
this->seqNoOfReq = 0;
}
}
return S_cas_success;
return S_cas_success;
}
//
@@ -380,32 +401,32 @@ caStatus casDGClient::versionAction ()
//
void casDGClient::sendBeacon ( ca_uint32_t beaconNumber )
{
union {
caHdr msg;
char buf;
};
union {
caHdr msg;
char buf;
};
//
// create the message
//
memset ( & buf, 0, sizeof ( msg ) );
//
// create the message
//
memset ( & buf, 0, sizeof ( msg ) );
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = CA_PROTO_RSRV_IS_UP;
AlignedWireRef < epicsUInt16 > ( msg.m_dataType ) = CA_MINOR_PROTOCOL_REVISION;
AlignedWireRef < epicsUInt32 > ( msg.m_cid ) = beaconNumber;
//
// send it to all addresses on the beacon list,
//
// send it to all addresses on the beacon list,
// but let the IO specific code set the address
// field and the port field
//
this->sendBeaconIO ( buf, sizeof (msg), msg.m_count, msg.m_available );
//
this->sendBeaconIO ( buf, sizeof (msg), msg.m_count, msg.m_available );
}
//
// casDGClient::xSend()
//
outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
bufSizeT nBytesToSend, bufSizeT & nBytesSent )
outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
bufSizeT nBytesToSend, bufSizeT & nBytesSent )
{
bufSizeT totalBytes = 0;
while ( totalBytes < nBytesToSend ) {
@@ -418,9 +439,9 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
unsigned sizeDG = pHdr->cadg_nBytes - sizeof ( *pHdr );
if ( pHdr->cadg_addr.isValid() ) {
outBufClient::flushCondition stat =
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
if ( stat != outBufClient::flushProgress ) {
outBufClient::flushCondition stat =
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
if ( stat != outBufClient::flushProgress ) {
break;
}
}
@@ -429,10 +450,10 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
}
if ( totalBytes ) {
//
// !! this time fetch may be slowing things down !!
//
//this->lastSendTS = epicsTime::getCurrent();
//
// !! this time fetch may be slowing things down !!
//
//this->lastSendTS = epicsTime::getCurrent();
nBytesSent = totalBytes;
return outBufClient::flushProgress;
}
@@ -455,16 +476,16 @@ inBufClient::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRe
while (pAfter-pCurBuf >= static_cast<int>(MAX_UDP_RECV+sizeof(cadg))) {
pHdr = reinterpret_cast < cadg * > ( pCurBuf );
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
MAX_UDP_RECV, parm, nDGBytesRecv, pHdr->cadg_addr);
if (stat==casFillProgress) {
if (stat==casFillProgress) {
pHdr->cadg_nBytes = nDGBytesRecv + sizeof(*pHdr);
pCurBuf += pHdr->cadg_nBytes;
//
// !! this time fetch may be slowing things down !!
//
//this->lastRecvTS = epicsTime::getCurrent();
}
//
// !! this time fetch may be slowing things down !!
//
//this->lastRecvTS = epicsTime::getCurrent();
}
else {
break;
}
@@ -487,9 +508,9 @@ inBufClient::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRe
// this results in many small UDP frames which unfortunately
// isnt particularly efficient
//
caStatus casDGClient::asyncSearchResponse (
caStatus casDGClient::asyncSearchResponse (
epicsGuard < casClientMutex > &, const caNetAddr & outAddr,
const caHdrLargeArray & msg, const pvExistReturn & retVal,
const caHdrLargeArray & msg, const pvExistReturn & retVal,
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber )
{
if ( retVal.getStatus() != pverExistsHere ) {
@@ -497,7 +518,7 @@ caStatus casDGClient::asyncSearchResponse (
}
void * pRaw;
const outBufCtx outctx = this->out.pushCtx
const outBufCtx outctx = this->out.pushCtx
( sizeof(cadg), MAX_UDP_SEND, pRaw );
if ( outctx.pushResult() != outBufCtx::pushCtxSuccess ) {
return S_cas_sendBlocked;
@@ -515,7 +536,7 @@ caStatus casDGClient::asyncSearchResponse (
pMsg->m_dataType = htons ( sequenceNoIsValid );
}
caStatus stat = this->searchResponse ( msg, retVal );
caStatus stat = this->searchResponse ( msg, retVal );
pRespHdr->cadg_nBytes = this->out.popCtx (outctx) + sizeof ( *pRespHdr );
if ( pRespHdr->cadg_nBytes > sizeof ( *pRespHdr ) + sizeof (caHdr) ) {
@@ -523,7 +544,7 @@ caStatus casDGClient::asyncSearchResponse (
this->out.commitRawMsg ( pRespHdr->cadg_nBytes );
}
return stat;
return stat;
}
//
@@ -533,8 +554,8 @@ caStatus casDGClient::processDG ()
{
bufSizeT bytesLeft;
caStatus status;
status = S_cas_success;
status = S_cas_success;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
bufSizeT dgInBytesConsumed;
const cadg * pReqHdr = reinterpret_cast < cadg * > ( this->in.msgPtr () );
@@ -561,9 +582,9 @@ caStatus casDGClient::processDG ()
// insert version header at the start of the reply message
this->sendVersion ();
cadg * pRespHdr = static_cast < cadg * > ( pRaw );
//
// select the next DG in the input stream and start processing it
//
@@ -593,7 +614,7 @@ caStatus casDGClient::processDG ()
// a) it used all of the incoming DG or
// b) it used all of the outgoing DG
//
// In either case commit the DG to the protocol stream and
// In either case commit the DG to the protocol stream and
// release the send lock
//
// if there are not additional messages passed the version header
@@ -653,7 +674,7 @@ caStatus casDGClient::processDG ()
//
unsigned casDGClient::getDebugLevel() const
{
return this->getCAS().getDebugLevel();
return this->getCAS().getDebugLevel();
}
//
@@ -661,7 +682,7 @@ unsigned casDGClient::getDebugLevel() const
//
caNetAddr casDGClient::fetchLastRecvAddr () const
{
return this->lastRecvAddr;
return this->lastRecvAddr;
}
//
@@ -669,7 +690,7 @@ caNetAddr casDGClient::fetchLastRecvAddr () const
//
ca_uint32_t casDGClient::datagramSequenceNumber () const
{
return this->seqNoOfReq;
return this->seqNoOfReq;
}
//
@@ -684,7 +705,7 @@ void casDGClient::hostName ( char *pBufIn, unsigned bufSizeIn ) const
void casDGClient::sendVersion ()
{
epicsGuard < epicsMutex > guard ( this->mutex );
caStatus status = this->out.copyInHeader ( CA_PROTO_VERSION, 0,
caStatus status = this->out.copyInHeader ( CA_PROTO_VERSION, 0,
0, CA_MINOR_PROTOCOL_REVISION, 0, 0, 0 );
if ( ! status ) {
this->out.commitMsg ();
@@ -729,27 +750,27 @@ outBufClient::flushCondition casDGClient::flush ()
//
caStatus casDGClient::processMsg ()
{
int status = S_cas_success;
int status = S_cas_success;
try {
unsigned bytesLeft;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
unsigned bytesLeft;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
caHdrLargeArray msgTmp;
unsigned msgSize;
ca_uint32_t hdrSize;
char * rawMP;
{
//
// copy as raw bytes in order to avoid
// alignment problems
//
//
// copy as raw bytes in order to avoid
// alignment problems
//
caHdr smallHdr;
if ( bytesLeft < sizeof ( smallHdr ) ) {
break;
}
rawMP = this->in.msgPtr ();
memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) );
memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) );
ca_uint32_t payloadSize = AlignedWireRef < epicsUInt16 > ( smallHdr.m_postsize );
ca_uint32_t nElem = AlignedWireRef < epicsUInt16 > ( smallHdr.m_count );
@@ -779,8 +800,8 @@ caStatus casDGClient::processMsg ()
msgTmp.m_available = AlignedWireRef < epicsUInt32 > ( smallHdr.m_available );
if ( payloadSize & 0x7 ) {
status = this->sendErr (
& msgTmp, invalidResID, ECA_INTERNAL,
status = this->sendErr (
& msgTmp, invalidResID, ECA_INTERNAL,
"CAS: Datagram request wasn't 8 byte aligned" );
this->in.removeMsg ( bytesLeft );
break;
@@ -789,7 +810,7 @@ caStatus casDGClient::processMsg ()
msgSize = hdrSize + payloadSize;
if ( bytesLeft < msgSize ) {
if ( msgSize > this->in.bufferSize() ) {
status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE,
status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE,
"client's request didnt fit within the CA server's message buffer" );
this->in.removeMsg ( bytesLeft );
}
@@ -798,95 +819,96 @@ caStatus casDGClient::processMsg ()
this->ctx.setMsg ( msgTmp, rawMP + hdrSize );
if ( this->getCAS().getDebugLevel() > 5u ) {
if ( this->getCAS().getDebugLevel() > 5u ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?",
caServerI::dumpMsg ( pHostName, "?",
& msgTmp, rawMP + hdrSize, 0 );
}
}
}
//
// Reset the context to the default
// (guarantees that previous message does not get mixed
// up with the current message)
//
this->ctx.setChannel ( NULL );
this->ctx.setPV ( NULL );
//
// Reset the context to the default
// (guarantees that previous message does not get mixed
// up with the current message)
//
this->ctx.setChannel ( NULL );
this->ctx.setPV ( NULL );
//
// Call protocol stub
//
//
// Call protocol stub
//
casDGClient::pCASMsgHandler pHandler;
if ( msgTmp.m_cmmd < NELEMENTS ( casDGClient::msgHandlers ) ) {
if ( msgTmp.m_cmmd < NELEMENTS ( casDGClient::msgHandlers ) ) {
pHandler = this->casDGClient::msgHandlers[msgTmp.m_cmmd];
}
}
else {
pHandler = & casDGClient::uknownMessageAction;
}
status = ( this->*pHandler ) ();
if ( status ) {
status = ( this->*pHandler ) ();
if ( status ) {
this->in.removeMsg ( this->in.bytesPresent() );
break;
}
break;
}
this->in.removeMsg ( msgSize );
}
}
}
catch ( std::exception & except ) {
this->in.removeMsg ( this->in.bytesPresent() );
status = this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"C++ exception \"%s\" in CA circuit server",
except.what () );
status = S_cas_internal;
}
catch (...) {
this->in.removeMsg ( this->in.bytesPresent() );
status = this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"unexpected C++ exception in CA datagram server" );
status = S_cas_internal;
}
return status;
return status;
}
//
// casDGClient::sendErr()
// casDGClient::sendErr()
//
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
ca_uint32_t cid, const int reportedStatus, const char *pformat, ... )
{
unsigned stringSize;
char msgBuf[1024]; /* allocate plenty of space for the message string */
if ( pformat ) {
va_list args;
va_start ( args, pformat );
int status = vsprintf ( msgBuf, pformat, args );
if ( status < 0 ) {
errPrintf (S_cas_internal, __FILE__, __LINE__,
"bad sendErr(%s)", pformat);
stringSize = 0u;
}
else {
stringSize = 1u + (unsigned) status;
}
}
else {
stringSize = 0u;
}
unsigned stringSize;
char msgBuf[1024]; /* allocate plenty of space for the message string */
if ( pformat ) {
va_list args;
va_start ( args, pformat );
int status = vsprintf ( msgBuf, pformat, args );
if ( status < 0 ) {
errPrintf (S_cas_internal, __FILE__, __LINE__,
"bad sendErr(%s)", pformat);
stringSize = 0u;
}
else {
stringSize = 1u + (unsigned) status;
}
va_end ( args );
}
else {
stringSize = 0u;
}
unsigned hdrSize = sizeof ( caHdr );
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
CA_V49( this->minor_version_number ) ) {
hdrSize += 2 * sizeof ( ca_uint32_t );
}
caHdr * pReqOut;
epicsGuard < epicsMutex > guard ( this->mutex );
caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR,
caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR,
hdrSize + stringSize, 0, 0, cid, reportedStatus,
reinterpret_cast <void **> ( & pReqOut ) );
if ( ! status ) {
@@ -896,7 +918,7 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
* copy back the request protocol
* (in network byte order)
*/
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
CA_V49( this->minor_version_number ) ) {
ca_uint32_t *pLW = ( ca_uint32_t * ) ( pReqOut + 1 );
pReqOut->m_cmmd = htons ( curp->m_cmmd );
@@ -927,7 +949,7 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
this->out.commitMsg ();
}
return S_cas_success;
return S_cas_success;
}
@@ -936,17 +958,17 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
//
caStatus casDGClient::echoAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const void * dp = this->ctx.getData();
const caHdrLargeArray * mp = this->ctx.getMsg();
const void * dp = this->ctx.getData();
void * pPayloadOut;
epicsGuard < epicsMutex > guard ( this->mutex );
caStatus status = this->out.copyInHeader ( mp->m_cmmd, mp->m_postsize,
caStatus status = this->out.copyInHeader ( mp->m_cmmd, mp->m_postsize,
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available,
& pPayloadOut );
if ( ! status ) {
memcpy ( pPayloadOut, dp, mp->m_postsize );
this->out.commitMsg ();
}
return S_cas_success;
return S_cas_success;
}

View File

@@ -205,7 +205,7 @@ caStatus casStrmClient :: processMsg ()
if ( bytesLeft < msgSize ) {
status = S_cas_success;
if ( msgSize > this->in.bufferSize() ) {
this->in.expandBuffer ();
this->in.expandBuffer (msgSize);
// msg to large - set up message drain
if ( msgSize > this->in.bufferSize() ) {
caServerI::dumpMsg ( this->pHostName, this->pUserName, & msgTmp, 0,
@@ -338,6 +338,16 @@ caStatus casStrmClient::versionAction ( epicsGuard < casClientMutex > & )
return S_cas_badProtocol;
}
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is too old\n",
pHostName );
}
return S_cas_badProtocol;
}
double tmp = mp->m_dataType - CA_PROTO_PRIORITY_MIN;
tmp *= epicsThreadPriorityCAServerHigh - epicsThreadPriorityCAServerLow;
tmp /= CA_PROTO_PRIORITY_MAX - CA_PROTO_PRIORITY_MIN;
@@ -409,7 +419,7 @@ caStatus casStrmClient::verifyRequest (casChannelI * & pChan , bool allowdyn)
//
// element count out of range ?
//
if ( ctx.msg.m_count > pChan->getPVI().nativeCount() ||
if ( ctx.msg.m_count > pChan->getMaxElem() ||
( !allowdyn && ctx.msg.m_count == 0u ) ) {
return ECA_BADCOUNT;
}
@@ -856,8 +866,20 @@ caStatus casStrmClient::monitorResponse (
casChannelI & chan, const caHdrLargeArray & msg,
const gdd & desc, const caStatus completionStatus )
{
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void * pPayload = 0;
@@ -883,7 +905,7 @@ caStatus casStrmClient::monitorResponse (
gdd * pDBRDD = 0;
if ( completionStatus == S_cas_success ) {
caStatus status = createDBRDD ( msg.m_dataType, count,
chan.getPVI().nativeCount(), pDBRDD );
chan.getMaxElem(), pDBRDD );
if ( status != S_cas_success ) {
caStatus ecaStatus;
if ( status == S_cas_badType ) {
@@ -1231,6 +1253,14 @@ caStatus casStrmClient :: searchResponse (
const pvExistReturn & retVal )
{
if ( retVal.getStatus() != pverExistsHere ) {
if (msg.m_dataType == DOREPLY ) {
long status = this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
msg.m_dataType, msg.m_count, msg.m_cid, msg.m_available, 0 );
if ( status == S_cas_success ) {
this->out.commitMsg ();
}
}
return S_cas_success;
}
@@ -1326,6 +1356,16 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\" but is too old\n",
pHostName, pChanName );
}
return S_cas_badProtocol;
}
//
// check the sanity of the message
//
@@ -1395,11 +1435,8 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
//
switch ( pver.getStatus() ) {
case pverExistsHere:
status = this->searchResponse ( guard, *mp, pver );
break;
case pverDoesNotExistHere:
status = S_cas_success;
status = this->searchResponse ( guard, *mp, pver );
break;
case pverAsyncCompletion:
@@ -1854,7 +1891,7 @@ caStatus casStrmClient::privateCreateChanResponse (
// the protocol buffer.
//
assert ( nativeTypeDBR <= 0xffff );
aitIndex nativeCount = chan.getPVI().nativeCount();
aitIndex nativeCount = chan.getMaxElem();
assert ( nativeCount <= 0xffffffff );
assert ( hdr.m_cid == chan.getCID() );
status = this->out.copyInHeader ( CA_PROTO_CREATE_CHAN, 0,
@@ -2614,7 +2651,7 @@ caStatus casStrmClient::read ()
{
gdd * pDD = 0;
caStatus status = createDBRDD ( pHdr->m_dataType, pHdr->m_count,
this->ctx.getChannel()->getPVI().nativeCount(), pDD );
this->ctx.getChannel()->getMaxElem(), pDD );
if ( status != S_cas_success ) {
return status;
}
@@ -2761,6 +2798,7 @@ caStatus casStrmClient::sendErr ( epicsGuard <casClientMutex> &,
else {
stringSize = 1u + (unsigned) status;
}
va_end ( args );
}
else {
stringSize = 0u;

View File

@@ -13,42 +13,54 @@
* 505 665 1831
*/
#include <new>
#include <stdlib.h>
#include "epicsAssert.h"
#include "freeList.h"
#define epicsExportSharedSymbols
#include "clientBufMemoryManager.h"
#include "caProto.h"
bufSizeT clientBufMemoryManager::maxSize () const
clientBufMemoryManager::clientBufMemoryManager()
:smallBufFreeList ( 0 )
{
return bufferFactory.largeBufferSize ();
freeListInitPvt ( & this->smallBufFreeList, MAX_MSG_SIZE, 8 );
}
clientBufMemoryManager::~clientBufMemoryManager()
{
freeListCleanup ( this->smallBufFreeList );
}
casBufferParm clientBufMemoryManager::allocate ( bufSizeT newMinSize )
{
casBufferParm parm;
if ( newMinSize <= bufferFactory.smallBufferSize () ) {
parm.pBuf = bufferFactory.newSmallBuffer ();
parm.bufSize = bufferFactory.smallBufferSize ();
}
else if ( newMinSize <= bufferFactory.largeBufferSize () ) {
parm.pBuf = bufferFactory.newLargeBuffer ();
parm.bufSize = bufferFactory.largeBufferSize ();
if ( newMinSize <= MAX_MSG_SIZE ) {
parm.pBuf = (char*)freeListMalloc(this->smallBufFreeList);
parm.bufSize = MAX_MSG_SIZE;
}
else {
parm.pBuf = static_cast < char * > ( ::operator new ( newMinSize ) );
// round size up to multiple of 4K
newMinSize = ((newMinSize-1)|0xfff)+1;
parm.pBuf = (char*)malloc(newMinSize);
parm.bufSize = newMinSize;
}
if(!parm.pBuf)
throw std::bad_alloc();
return parm;
}
void clientBufMemoryManager::release ( char * pBuf, bufSizeT bufSize )
{
if ( bufSize == bufferFactory.smallBufferSize () ) {
bufferFactory.destroySmallBuffer ( pBuf );
}
else if ( bufSize == bufferFactory.largeBufferSize () ) {
bufferFactory.destroyLargeBuffer ( pBuf );
assert(pBuf);
if (bufSize <= MAX_MSG_SIZE) {
freeListFree(this->smallBufFreeList, pBuf);
}
else {
::operator delete ( pBuf );
free(pBuf);
}
}

View File

@@ -16,22 +16,6 @@
typedef unsigned bufSizeT;
static const unsigned bufSizeT_MAX = UINT_MAX;
class casBufferFactory {
public:
casBufferFactory ();
~casBufferFactory ();
unsigned smallBufferSize () const;
char * newSmallBuffer ();
void destroySmallBuffer ( char * pBuf );
unsigned largeBufferSize () const;
char * newLargeBuffer ();
void destroyLargeBuffer ( char * pBuf );
private:
void * smallBufFreeList;
void * largeBufFreeList;
unsigned largeBufferSizePriv;
};
struct casBufferParm {
char * pBuf;
bufSizeT bufSize;
@@ -39,11 +23,15 @@ struct casBufferParm {
class clientBufMemoryManager {
public:
clientBufMemoryManager();
~clientBufMemoryManager();
//! @throws std::bad_alloc on failure
casBufferParm allocate ( bufSizeT newMinSize );
void release ( char * pBuf, bufSizeT bufSize );
bufSizeT maxSize () const;
private:
casBufferFactory bufferFactory;
void * smallBufFreeList;
};
#endif // clientBufMemoryManagerh

View File

@@ -13,6 +13,9 @@
* 505 665 1831
*/
#include <stdexcept>
#include <new>
#include <stdio.h>
#include <string.h>
@@ -155,11 +158,17 @@ bufSizeT inBuf::popCtx ( const inBufCtx &ctx )
}
}
void inBuf::expandBuffer ()
void inBuf::expandBuffer (bufSizeT needed)
{
bufSizeT max = this->memMgr.maxSize();
if ( this->bufSize < max ) {
casBufferParm bufParm = this->memMgr.allocate ( max );
if (needed > bufSize) {
casBufferParm bufParm;
try {
bufParm = this->memMgr.allocate ( needed );
} catch (std::bad_alloc& e) {
// caller must check that buffer size has expended
return;
}
bufSizeT unprocessedBytes = this->bytesPresent ();
memcpy ( bufParm.pBuf, &this->pBuf[this->nextReadIndex], unprocessedBytes );
this->bytesInBuffer = unprocessedBytes;
@@ -170,7 +179,7 @@ void inBuf::expandBuffer ()
}
}
unsigned inBuf::bufferSize () const
bufSizeT inBuf::bufferSize() const
{
return this->bufSize;
}

View File

@@ -82,8 +82,8 @@ public:
//
const inBufCtx pushCtx ( bufSizeT headerSize, bufSizeT bodySize );
bufSizeT popCtx ( const inBufCtx & ); // returns actual size
unsigned bufferSize () const;
void expandBuffer ();
bufSizeT bufferSize () const;
void expandBuffer (bufSizeT needed);
private:
class inBufClient & client;
class clientBufMemoryManager & memMgr;

View File

@@ -59,7 +59,7 @@ caStatus outBuf::allocRawMsg ( bufSizeT msgsize, void **ppMsg )
msgsize = CA_MESSAGE_ALIGN ( msgsize );
if ( msgsize > this->bufSize ) {
this->expandBuffer ();
this->expandBuffer (msgsize);
if ( msgsize > this->bufSize ) {
return S_cas_hugeRequest;
}
@@ -316,11 +316,17 @@ void outBuf::show (unsigned level) const
}
}
void outBuf::expandBuffer ()
void outBuf::expandBuffer (bufSizeT needed)
{
bufSizeT max = this->memMgr.maxSize();
if ( this->bufSize < max ) {
casBufferParm bufParm = this->memMgr.allocate ( max );
if (needed > bufSize) {
casBufferParm bufParm;
try {
bufParm = this->memMgr.allocate ( needed );
} catch (std::bad_alloc& e) {
// caller must check that buffer size has expended
return;
}
memcpy ( bufParm.pBuf, this->pBuf, this->stack );
this->memMgr.release ( this->pBuf, this->bufSize );
this->pBuf = bufParm.pBuf;

View File

@@ -122,7 +122,7 @@ private:
bufSizeT stack;
unsigned ctxRecursCount;
void expandBuffer ();
void expandBuffer (bufSizeT needed);
outBuf ( const outBuf & );
outBuf & operator = ( const outBuf & );

View File

@@ -1,29 +0,0 @@
/*************************************************************************\
* Copyright (c) 2008 UChicago Argonne LLC, 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.
\*************************************************************************/
#define epicsExportSharedSymbols
#include "ipIgnoreEntry.h"
#include "casChannelI.h"
#ifdef _MSC_VER
# pragma warning ( push )
# pragma warning ( disable:4660 )
#endif
template class resTable < ipIgnoreEntry, ipIgnoreEntry >;
template class resTable < casChannelI, chronIntId >;
template class resTable < casEventMaskEntry, stringId >;
template class chronIntIdResTable < casChannelI >;
template class tsFreeList < casMonEvent, 1024, epicsMutexNOOP >;
template class tsFreeList < casMonitor, 1024, epicsMutex >;
#ifdef _MSC_VER
# pragma warning ( pop )
#endif

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.
\*************************************************************************/
//
@@ -32,7 +32,7 @@ const unsigned caServerConnectPendQueueSize = 5u;
//
// casIntfIO::casIntfIO()
//
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
sock ( INVALID_SOCKET ),
addr ( addrIn.getSockIP() )
{
@@ -40,80 +40,79 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
osiSocklen_t addrSize;
bool portChange;
if ( ! osiSockAttach () ) {
throw S_cas_internal;
}
if ( ! osiSockAttach () ) {
throw S_cas_internal;
}
/*
* Setup the server socket
*/
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (this->sock==INVALID_SOCKET) {
/*
* Setup the server socket
*/
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (this->sock == INVALID_SOCKET) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
printf ( "No socket error was %s\n", sockErrBuf );
throw S_cas_noFD;
}
printf ( "No socket error was %s\n", sockErrBuf );
throw S_cas_noFD;
}
epicsSocketEnableAddressReuseDuringTimeWaitState ( this->sock );
status = bind ( this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
if (status<0) {
if (SOCKERRNO == SOCK_EADDRINUSE) {
//
// enable assignment of a default port
// (so the getsockname() call below will
// work correctly)
//
this->addr.sin_port = ntohs (0);
status = bind(
status = bind ( this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
if (status < 0) {
if (SOCKERRNO == SOCK_EADDRINUSE ||
SOCKERRNO == SOCK_EACCES) {
//
// enable assignment of a default port
// (so the getsockname() call below will
// work correctly)
//
this->addr.sin_port = ntohs (0);
status = bind(
this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
}
if (status<0) {
}
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
char buf[64];
ipAddrToA (&this->addr, buf, sizeof(buf));
errPrintf ( S_cas_bindFail,
__FILE__, __LINE__,
"- bind TCP IP addr=%s failed because %s",
buf, sockErrBuf );
char buf[64];
ipAddrToA (&this->addr, buf, sizeof(buf));
errlogPrintf ( "CAS: Socket bind TCP to %s failed with %s",
buf, sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_bindFail;
}
throw S_cas_bindFail;
}
portChange = true;
}
}
else {
portChange = false;
}
addrSize = ( osiSocklen_t ) sizeof (this->addr);
status = getsockname (
this->sock,
reinterpret_cast <sockaddr *> ( &this->addr ),
addrSize = ( osiSocklen_t ) sizeof (this->addr);
status = getsockname (
this->sock,
reinterpret_cast <sockaddr *> ( &this->addr ),
&addrSize );
if (status) {
if (status) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "CAS: getsockname() error %s\n",
sockErrBuf );
errlogPrintf ( "CAS: getsockname() error %s\n",
sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_internal;
}
throw S_cas_internal;
}
//
// be sure of this now so that we can fetch the IP
// address and port number later
//
//
// be sure of this now so that we can fetch the IP
// address and port number later
//
assert (this->addr.sin_family == AF_INET);
if ( portChange ) {
errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n");
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
ntohs (this->addr.sin_port) );
errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n");
errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" );
@@ -121,12 +120,12 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
}
status = listen(this->sock, caServerConnectPendQueueSize);
if(status < 0) {
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_internal;
throw S_cas_internal;
}
}
@@ -135,17 +134,17 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
//
casIntfIO::~casIntfIO()
{
if (this->sock != INVALID_SOCKET) {
epicsSocketDestroy (this->sock);
}
if (this->sock != INVALID_SOCKET) {
epicsSocketDestroy (this->sock);
}
osiSockRelease ();
osiSockRelease ();
}
//
// newStreamIO::newStreamClient()
//
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
clientBufMemoryManager & bufMgr ) const
{
static bool oneMsgFlag = false;
@@ -175,14 +174,14 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
args.sock = newSock;
casStreamOS * pOS = new casStreamOS ( cas, bufMgr, args );
if ( ! pOS ) {
errMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"unable to create data structures for a new client" );
epicsSocketDestroy ( newSock );
}
else {
if ( cas.getDebugLevel() > 0u ) {
char pName[64u];
pOS->hostName ( pName, sizeof ( pName ) );
errlogPrintf ( "CAS: allocated client object for \"%s\"\n", pName );
}
@@ -197,7 +196,7 @@ void casIntfIO::setNonBlocking()
{
int status;
osiSockIoctl_t yes = true;
status = socket_ioctl(this->sock, FIONBIO, &yes);
if ( status < 0 ) {
char sockErrBuf[64];

View File

@@ -23,5 +23,4 @@ dbCore_SRCS += asIocRegister.c
PROD_HOST += ascheck
ascheck_SRCS = ascheck.c
ascheck_LIBS = dbCore
ascheck_LIBS = dbCore ca

View File

@@ -14,14 +14,18 @@ SRC_DIRS += $(IOCDIR)/db
INC += callback.h
INC += dbAccess.h
INC += dbAccessDefs.h
INC += dbCa.h
INC += dbAddr.h
INC += dbBkpt.h
INC += dbCa.h
INC += dbChannel.h
INC += dbConstLink.h
INC += dbConvert.h
INC += dbConvertFast.h
INC += dbConvertJSON.h
INC += dbDbLink.h
INC += dbExtractArray.h
INC += dbEvent.h
INC += dbJLink.h
INC += dbLink.h
INC += dbLock.h
INC += dbNotify.h
@@ -64,9 +68,13 @@ dbCore_SRCS += dbLock.c
dbCore_SRCS += dbAccess.c
dbCore_SRCS += dbBkpt.c
dbCore_SRCS += dbChannel.c
dbCore_SRCS += dbConstLink.c
dbCore_SRCS += dbConvert.c
dbCore_SRCS += dbConvertJSON.c
dbCore_SRCS += dbDbLink.c
dbCore_SRCS += dbFastLinkConv.c
dbCore_SRCS += dbExtractArray.c
dbCore_SRCS += dbJLink.c
dbCore_SRCS += dbLink.c
dbCore_SRCS += dbNotify.c
dbCore_SRCS += dbScan.c
@@ -85,7 +93,6 @@ dbCore_SRCS += dbChannelIO.cpp
dbCore_SRCS += dbSubscriptionIO.cpp
dbCore_SRCS += dbPutNotifyBlocker.cpp
dbCore_SRCS += dbContextReadNotifyCache.cpp
dbCore_SRCS += templateInstances.cpp
dbCore_SRCS += dbIocRegister.c
dbCore_SRCS += chfPlugin.c
dbCore_SRCS += dbState.c

View File

@@ -24,7 +24,6 @@
#include "dbDefs.h"
#include "epicsAtomic.h"
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsInterrupt.h"
#include "epicsRingPointer.h"
#include "epicsString.h"
@@ -92,7 +91,7 @@ static int priorityValue[NUM_CALLBACK_PRIORITIES] = {0, 1, 2};
int callbackSetQueueSize(int size)
{
if (callbackIsInit) {
errlogPrintf("Callback system already initialized\n");
fprintf(stderr, "Callback system already initialized\n");
return -1;
}
callbackQueueSize = size;
@@ -102,7 +101,7 @@ int callbackSetQueueSize(int size)
int callbackParallelThreads(int count, const char *prio)
{
if (callbackIsInit) {
errlogPrintf("Callback system already initialized\n");
fprintf(stderr, "Callback system already initialized\n");
return -1;
}
@@ -112,7 +111,7 @@ int callbackParallelThreads(int count, const char *prio)
count = callbackParallelThreadsDefault;
if (count < 1) count = 1;
if (!prio || strcmp(prio, "") == 0 || strcmp(prio, "*") == 0) {
if (!prio || *prio == 0 || strcmp(prio, "*") == 0) {
int i;
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
@@ -121,30 +120,30 @@ int callbackParallelThreads(int count, const char *prio)
}
else {
dbMenu *pdbMenu;
int i;
if (!pdbbase) {
errlogPrintf("callbackParallelThreads: pdbbase not set\n");
fprintf(stderr, "callbackParallelThreads: pdbbase not set\n");
return -1;
}
/* Find prio in menuPriority */
pdbMenu = dbFindMenu(pdbbase, "menuPriority");
if (pdbMenu) {
int i, gotMatch = 0;
for (i = 0; i < pdbMenu->nChoice; i++) {
gotMatch = (epicsStrCaseCmp(prio, pdbMenu->papChoiceValue[i])==0) ? TRUE : FALSE;
if (gotMatch)
break;
}
if (gotMatch) {
callbackQueue[i].threadsConfigured = count;
return 0;
}
else {
errlogPrintf("Unknown priority \"%s\"\n", prio);
return -1;
}
if (!pdbMenu) {
fprintf(stderr, "callbackParallelThreads: No Priority menu\n");
return -1;
}
for (i = 0; i < pdbMenu->nChoice; i++) {
if (epicsStrCaseCmp(prio, pdbMenu->papChoiceValue[i]) == 0)
goto found;
}
fprintf(stderr, "callbackParallelThreads: "
"Unknown priority \"%s\"\n", prio);
return -1;
found:
callbackQueue[i].threadsConfigured = count;
}
return 0;
}

View File

@@ -46,14 +46,16 @@ typedef struct callbackPvt {
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
#define callbackSetCallback(PFUN,PCALLBACK)\
( (PCALLBACK)->callback = (PFUN) )
#define callbackSetPriority(PRIORITY,PCALLBACK)\
( (PCALLBACK)->priority = (PRIORITY) )
#define callbackSetUser(USER,PCALLBACK)\
( (PCALLBACK)->user = (void *)(USER) )
#define callbackGetUser(USER,PCALLBACK)\
( (USER) = (void *)((CALLBACK *)(PCALLBACK))->user )
#define callbackSetCallback(PFUN, PCALLBACK) \
( (PCALLBACK)->callback = (PFUN) )
#define callbackSetPriority(PRIORITY, PCALLBACK) \
( (PCALLBACK)->priority = (PRIORITY) )
#define callbackGetPriority(PRIORITY, PCALLBACK) \
( (PRIORITY) = (PCALLBACK)->priority )
#define callbackSetUser(USER, PCALLBACK) \
( (PCALLBACK)->user = (void *) (USER) )
#define callbackGetUser(USER, PCALLBACK) \
( (USER) = (PCALLBACK)->user )
epicsShareFunc void callbackInit(void);
epicsShareFunc void callbackStop(void);

View File

@@ -41,8 +41,7 @@
#include "dbAddr.h"
#include "dbBase.h"
#include "dbBkpt.h"
#include "dbCa.h"
#include "dbCommon.h"
#include "dbCommonPvt.h"
#include "dbConvertFast.h"
#include "dbConvert.h"
#include "dbEvent.h"
@@ -50,11 +49,12 @@
#include "dbFldTypes.h"
#include "dbFldTypes.h"
#include "dbLink.h"
#include "dbLock.h"
#include "dbLockPvt.h"
#include "dbNotify.h"
#include "dbScan.h"
#include "dbServer.h"
#include "dbStaticLib.h"
#include "dbStaticPvt.h"
#include "devSup.h"
#include "epicsEvent.h"
#include "link.h"
@@ -77,6 +77,8 @@ static short mapDBFToDBR[DBF_NTYPES] = {
/* DBF_USHORT => */ DBR_USHORT,
/* DBF_LONG => */ DBR_LONG,
/* DBF_ULONG => */ DBR_ULONG,
/* DBF_INT64 => */ DBR_INT64,
/* DBF_UINT64 => */ DBR_UINT64,
/* DBF_FLOAT => */ DBR_FLOAT,
/* DBF_DOUBLE => */ DBR_DOUBLE,
/* DBF_ENUM, => */ DBR_ENUM,
@@ -107,7 +109,7 @@ void dbSpcAsRegisterCallback(SPC_ASCALLBACK func)
long dbPutSpecial(DBADDR *paddr,int pass)
{
long int (*pspecial)()=NULL;
struct rset *prset;
rset *prset;
dbCommon *precord = paddr->precord;
long status=0;
long special=paddr->special;
@@ -139,7 +141,7 @@ long dbPutSpecial(DBADDR *paddr,int pass)
}
static void get_enum_strs(DBADDR *paddr, char **ppbuffer,
struct rset *prset,long *options)
rset *prset,long *options)
{
short field_type=paddr->field_type;
dbFldDes *pdbFldDes = paddr->pfldDes;
@@ -199,7 +201,7 @@ choice_common:
}
static void get_graphics(DBADDR *paddr, char **ppbuffer,
struct rset *prset,long *options)
rset *prset,long *options)
{
struct dbr_grDouble grd;
int got_data=FALSE;
@@ -239,7 +241,7 @@ static void get_graphics(DBADDR *paddr, char **ppbuffer,
}
static void get_control(DBADDR *paddr, char **ppbuffer,
struct rset *prset,long *options)
rset *prset,long *options)
{
struct dbr_ctrlDouble ctrld;
int got_data=FALSE;
@@ -279,7 +281,7 @@ static void get_control(DBADDR *paddr, char **ppbuffer,
}
static void get_alarm(DBADDR *paddr, char **ppbuffer,
struct rset *prset, long *options)
rset *prset, long *options)
{
char *pbuffer = *ppbuffer;
struct dbr_alDouble ald = {epicsNAN, epicsNAN, epicsNAN, epicsNAN};
@@ -324,7 +326,7 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
void *pflin)
{
db_field_log *pfl= (db_field_log *)pflin;
struct rset *prset;
rset *prset;
short field_type;
dbCommon *pcommon;
char *pbuffer = *poriginal;
@@ -364,7 +366,7 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
memset(pbuffer, '\0', dbr_precision_size);
if((field_type==DBF_FLOAT || field_type==DBF_DOUBLE)
&& prset && prset->get_precision ){
(*prset->get_precision)(paddr,pbuffer);
(*prset->get_precision)(paddr,(long *)pbuffer);
} else {
*options ^= DBR_PRECISION; /*Turn off DBR_PRECISION*/
}
@@ -393,7 +395,7 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
*poriginal = pbuffer;
}
struct rset * dbGetRset(const struct dbAddr *paddr)
rset * dbGetRset(const struct dbAddr *paddr)
{
struct dbFldDes *pfldDes = paddr->pfldDes;
@@ -467,7 +469,7 @@ long dbScanPassive(dbCommon *pfrom, dbCommon *pto)
*/
long dbProcess(dbCommon *precord)
{
struct rset *prset = precord->rset;
rset *prset = precord->rset;
dbRecordType *pdbRecordType = precord->rdes;
unsigned char tpro = precord->tpro;
char context[40] = "";
@@ -646,7 +648,7 @@ long dbNameToAddr(const char *pname, DBADDR *paddr)
paddr->dbr_field_type = mapDBFToDBR[dbfType];
if (paddr->special == SPC_DBADDR) {
struct rset *prset = dbGetRset(paddr);
rset *prset = dbGetRset(paddr);
/* Let record type modify paddr */
if (prset && prset->cvt_dbaddr) {
@@ -667,7 +669,7 @@ long dbNameToAddr(const char *pname, DBADDR *paddr)
paddr->dbr_field_type = DBR_CHAR;
} else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
/* Clients see a char array, but keep original dbfType */
paddr->no_elements = PVNAME_STRINGSZ + 12;
paddr->no_elements = PVLINK_STRINGSZ;
paddr->field_size = 1;
paddr->dbr_field_type = DBR_CHAR;
} else {
@@ -681,6 +683,32 @@ finish:
return status;
}
void dbInitEntryFromAddr(struct dbAddr *paddr, DBENTRY *pdbentry)
{
struct dbCommon *prec = paddr->precord;
dbCommonPvt *ppvt = CONTAINER(prec, dbCommonPvt, common);
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
pdbentry->pdbbase = pdbbase;
pdbentry->precordType = prec->rdes;
pdbentry->precnode = ppvt->recnode;
pdbentry->pflddes = paddr->pfldDes;
pdbentry->pfield = paddr->pfield;
pdbentry->indfield = paddr->pfldDes->indRecordType;
}
void dbInitEntryFromRecord(struct dbCommon *prec, DBENTRY *pdbentry)
{
dbCommonPvt *ppvt = CONTAINER(prec, dbCommonPvt, common);
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
pdbentry->pdbbase = pdbbase;
pdbentry->precordType = prec->rdes;
pdbentry->precnode = ppvt->recnode;
}
long dbValueSize(short dbr_type)
{
/* sizes for value associated with each DBR request type */
@@ -692,6 +720,8 @@ long dbValueSize(short dbr_type)
sizeof(epicsUInt16), /* USHORT */
sizeof(epicsInt32), /* LONG */
sizeof(epicsUInt32), /* ULONG */
sizeof(epicsInt64), /* INT64 */
sizeof(epicsUInt64), /* UINT64 */
sizeof(epicsFloat32), /* FLOAT */
sizeof(epicsFloat64), /* DOUBLE */
sizeof(epicsEnum16)}; /* ENUM */
@@ -738,28 +768,34 @@ static long getLinkValue(DBADDR *paddr, short dbrType,
{
dbCommon *precord = paddr->precord;
dbFldDes *pfldDes = paddr->pfldDes;
/* size of pbuf storage in bytes, including space for trailing nil */
int maxlen;
DBENTRY dbEntry;
long status;
long nReq = nRequest ? *nRequest : 1;
/* dbFindRecord() below will always succeed as we have a
* valid DBADDR, so no point to check again.
* Request for zero elements always succeeds
*/
if(!nReq)
return 0;
switch (dbrType) {
case DBR_STRING:
maxlen = MAX_STRING_SIZE - 1;
if (nRequest && *nRequest > 1) *nRequest = 1;
maxlen = MAX_STRING_SIZE;
nReq = 1;
break;
case DBR_DOUBLE: /* Needed for dbCa links */
if (nRequest && *nRequest) *nRequest = 1;
if (nRequest) *nRequest = 1;
*(double *)pbuf = epicsNAN;
return 0;
case DBR_CHAR:
case DBR_UCHAR:
if (nRequest && *nRequest > 0) {
maxlen = *nRequest - 1;
break;
}
/* else fall through ... */
maxlen = nReq;
break;
default:
return S_db_badDbrtype;
}
@@ -768,10 +804,13 @@ static long getLinkValue(DBADDR *paddr, short dbrType,
status = dbFindRecord(&dbEntry, precord->name);
if (!status) status = dbFindField(&dbEntry, pfldDes->name);
if (!status) {
char *rtnString = dbGetString(&dbEntry);
const char *rtnString = dbGetString(&dbEntry);
strncpy(pbuf, rtnString, --maxlen);
pbuf[maxlen] = 0;
strncpy(pbuf, rtnString, maxlen-1);
pbuf[maxlen-1] = 0;
if(dbrType!=DBR_STRING)
nReq = strlen(pbuf)+1;
if(nRequest) *nRequest = nReq;
}
dbFinishEntry(&dbEntry);
return status;
@@ -781,28 +820,31 @@ static long getAttrValue(DBADDR *paddr, short dbrType,
char *pbuf, long *nRequest)
{
int maxlen;
long nReq = nRequest ? *nRequest : 1;
if (!paddr->pfield) return S_db_badField;
switch (dbrType) {
case DBR_STRING:
maxlen = MAX_STRING_SIZE - 1;
if (nRequest && *nRequest > 1) *nRequest = 1;
maxlen = MAX_STRING_SIZE;
nReq = 1;
break;
case DBR_CHAR:
case DBR_UCHAR:
if (nRequest && *nRequest > 0) {
maxlen = *nRequest - 1;
break;
}
maxlen = nReq;
break;
/* else fall through ... */
default:
return S_db_badDbrtype;
}
strncpy(pbuf, paddr->pfield, --maxlen);
pbuf[maxlen] = 0;
strncpy(pbuf, paddr->pfield, maxlen-1);
pbuf[maxlen-1] = 0;
if(dbrType!=DBR_STRING)
nReq = strlen(pbuf)+1;
if(nRequest) *nRequest = nReq;
return 0;
}
@@ -826,7 +868,7 @@ long dbGet(DBADDR *paddr, short dbrType,
db_field_log *pfl = (db_field_log *)pflin;
short field_type;
long capacity, no_elements, offset;
struct rset *prset;
rset *prset;
long status = 0;
if (options && *options)
@@ -930,6 +972,15 @@ long dbGet(DBADDR *paddr, short dbrType,
localAddr.pfield = (char *) pfl->u.r.field;
status = convert(&localAddr, pbuf, n, capacity, offset);
}
if(!status && dbrType==DBF_CHAR && nRequest &&
paddr->pfldDes && paddr->pfldDes->field_type==DBF_STRING)
{
/* long string ensure nil and truncate to actual length */
long nReq = *nRequest;
pbuf[nReq-1] = '\0';
*nRequest = strlen(pbuf)+1;
}
}
done:
paddr->pfield = pfieldsave;
@@ -952,19 +1003,25 @@ devSup* dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset) {
static long dbPutFieldLink(DBADDR *paddr,
short dbrType, const void *pbuffer, long nRequest)
{
dbLinkInfo link_info;
DBADDR *pdbaddr = NULL;
dbCommon *precord = paddr->precord;
dbCommon *lockrecs[2];
dbLocker locker;
dbFldDes *pfldDes = paddr->pfldDes;
long special = paddr->special;
struct link *plink = (struct link *)paddr->pfield;
const char *pstring = (const char *)pbuffer;
DBENTRY dbEntry;
struct dsxt *old_dsxt = NULL;
struct dset *new_dset = NULL;
struct dsxt *new_dsxt = NULL;
devSup *new_devsup = NULL;
long status;
int isDevLink;
short scan;
STATIC_ASSERT(DBLOCKER_NALLOC>=2);
switch (dbrType) {
case DBR_CHAR:
case DBR_UCHAR:
@@ -979,31 +1036,57 @@ static long dbPutFieldLink(DBADDR *paddr,
return S_db_badDbrtype;
}
dbInitEntry(pdbbase, &dbEntry);
status = dbFindRecord(&dbEntry, precord->name);
if (!status) status = dbFindField(&dbEntry, pfldDes->name);
if (status) goto finish;
status = dbParseLink(pstring, pfldDes->field_type, &link_info, 0);
if (status)
return status;
if (link_info.ltype == PV_LINK &&
(link_info.modifiers & (pvlOptCA | pvlOptCP | pvlOptCPP)) == 0) {
DBADDR tempaddr;
if (dbNameToAddr(link_info.target, &tempaddr)==0) {
/* This will become a DB link. */
pdbaddr = malloc(sizeof(*pdbaddr));
if (!pdbaddr) {
status = S_db_noMemory;
goto cleanup;
}
*pdbaddr = tempaddr; /* struct copy */
}
}
isDevLink = ellCount(&precord->rdes->devList) > 0 &&
(strcmp(pfldDes->name, "INP") == 0 ||
strcmp(pfldDes->name, "OUT") == 0);
pfldDes->isDevLink;
dbLockSetGblLock();
dbLockSetRecordLock(precord);
memset(&locker, 0, sizeof(locker));
lockrecs[0] = precord;
lockrecs[1] = pdbaddr ? pdbaddr->precord : NULL;
dbLockerPrepare(&locker, lockrecs, 2);
dbScanLockMany(&locker);
scan = precord->scan;
if (isDevLink) {
devSup *pdevSup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
if (pdevSup) {
new_dset = pdevSup->pdset;
new_dsxt = pdevSup->pdsxt;
new_devsup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
if (new_devsup) {
new_dset = new_devsup->pdset;
new_dsxt = new_devsup->pdsxt;
}
}
if (dbCanSetLink(plink, &link_info, new_devsup)) {
/* link type mis-match prevents assignment */
status = S_dbLib_badField;
goto unlock;
}
if (isDevLink) {
if (precord->dset) {
pdevSup = dbDSETtoDevSup(precord->rdes, precord->dset);
if (pdevSup)
old_dsxt = pdevSup->pdsxt;
devSup *old_devsup = dbDSETtoDevSup(precord->rdes, precord->dset);
if (old_devsup)
old_dsxt = old_devsup->pdsxt;
}
if (new_dsxt == NULL ||
@@ -1026,30 +1109,17 @@ static long dbPutFieldLink(DBADDR *paddr,
}
}
switch (plink->type) { /* Old link type */
case DB_LINK:
case CA_LINK:
dbRemoveLink(plink);
break;
case PV_LINK:
case CONSTANT:
break; /* do nothing */
case MACRO_LINK:
break; /* should never get here */
default: /* Hardware address */
if (!isDevLink) {
status = S_db_badHWaddr;
goto restoreScan;
}
break;
if (dbLinkIsDefined(plink)) {
dbRemoveLink(&locker, plink); /* Clear out old link */
}
else if (!isDevLink) {
status = S_db_badHWaddr;
goto restoreScan;
}
if (special) status = dbPutSpecial(paddr, 0);
if (!status) status = dbPutString(&dbEntry, pstring);
if (!status) status = dbSetLink(plink, &link_info, new_devsup);
if (!status && special) status = dbPutSpecial(paddr, 1);
@@ -1076,11 +1146,10 @@ static long dbPutFieldLink(DBADDR *paddr,
switch (plink->type) { /* New link type */
case PV_LINK:
dbAddLink(precord, plink, pfldDes->field_type);
break;
case CONSTANT:
break; /* do nothing */
case JSON_LINK:
dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr);
break;
case DB_LINK:
case CA_LINK:
@@ -1106,9 +1175,10 @@ postScanEvent:
if (scan != precord->scan)
db_post_events(precord, &precord->scan, DBE_VALUE | DBE_LOG);
unlock:
dbLockSetGblUnlock();
finish:
dbFinishEntry(&dbEntry);
dbScanUnlockMany(&locker);
dbLockerFinalize(&locker);
cleanup:
free(link_info.target);
return status;
}
@@ -1194,7 +1264,7 @@ long dbPut(DBADDR *paddr, short dbrType,
long no_elements = paddr->no_elements;
long special = paddr->special;
void *pfieldsave = paddr->pfield;
struct rset *prset = dbGetRset(paddr);
rset *prset = dbGetRset(paddr);
long status = 0;
long offset;
dbFldDes *pfldDes;

View File

@@ -20,6 +20,7 @@
#include "epicsTime.h"
#include "dbBase.h"
#include "dbAddr.h"
#include "recSup.h"
#ifdef INCLdb_accessh_epicsExportSharedSymbols
# define epicsExportSharedSymbols
@@ -181,6 +182,7 @@ struct dbr_alDouble {DBRalDouble};
#define S_db_badChoice (M_dbAccess|13) /*Illegal choice*/
#define S_db_badField (M_dbAccess|15) /*Illegal field value*/
#define S_db_lsetLogic (M_dbAccess|17) /*Logic error generating lock sets*/
#define S_db_noLSET (M_dbAccess|21) /*No link support table or entry*/
#define S_db_noRSET (M_dbAccess|31) /*missing record support entry table*/
#define S_db_noSupport (M_dbAccess|33) /*RSET or DSXT routine not defined*/
#define S_db_BadSub (M_dbAccess|35) /*Subroutine not found*/
@@ -202,7 +204,7 @@ struct dbr_alDouble {DBRalDouble};
#define S_db_bufFull (M_dbAccess|68) /*Buffer full*/
epicsShareFunc long dbPutSpecial(struct dbAddr *paddr,int pass);
epicsShareFunc struct rset * dbGetRset(const struct dbAddr *paddr);
epicsShareFunc rset * dbGetRset(const struct dbAddr *paddr);
epicsShareFunc long dbPutAttribute(
const char *recordTypename,const char *name,const char*value);
epicsShareFunc int dbIsValueField(const struct dbFldDes *pdbFldDes);

View File

@@ -26,12 +26,13 @@
#include "stdlib.h"
#include <memory> // std::auto_ptr
#include "tsDLList.h"
#include "tsFreeList.h"
#include "resourceLib.h"
#include "cacIO.h"
#include "compilerDependencies.h"
#include "epicsMemory.h"
#ifdef dbCACh_restore_epicsExportSharedSymbols
# define epicsExportSharedSymbols
@@ -193,8 +194,9 @@ private:
epicsMutex & mutex;
epicsMutex & cbMutex;
cacContextNotify & notify;
epics_auto_ptr < cacContext > pNetContext;
std::auto_ptr < cacContext > pNetContext;
char * pStateNotifyCache;
bool isolated;
cacChannel & createChannel (
epicsGuard < epicsMutex > &,

View File

@@ -11,7 +11,7 @@
* Original Authors: Bob Dalesio and Marty Kraimer
* Date: 26MAR96
*/
#define EPICS_DBCA_PRIVATE_API
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
@@ -28,6 +28,7 @@
#include "epicsPrint.h"
#include "epicsString.h"
#include "epicsThread.h"
#include "epicsAtomic.h"
#include "epicsTime.h"
#include "errlog.h"
#include "errMdef.h"
@@ -44,13 +45,18 @@
#include "dbCaPvt.h"
#include "dbCommon.h"
#include "db_convert.h"
#include "dbLink.h"
#include "dbLock.h"
#include "dbScan.h"
#include "link.h"
#include "recGbl.h"
#include "recSup.h"
/* defined in dbContext.cpp
* Setup local CA access
*/
extern void dbServiceIOInit();
extern int dbServiceIsolate;
static ELLLIST workList = ELLLIST_INIT; /* Work list for dbCaTask */
static epicsMutexId workListLock; /*Mutual exclusions semaphores for workList*/
@@ -58,7 +64,7 @@ static epicsEventId workListEvent; /*wakeup event for dbCaTask*/
static int removesOutstanding = 0;
#define removesOutstandingWarning 10000
static volatile enum {
static volatile enum dbCaCtl_t {
ctlInit, ctlRun, ctlPause, ctlExit
} dbCaCtl;
static epicsEventId startStopEvent;
@@ -68,57 +74,47 @@ struct ca_client_context * dbCaClientContext;
/* Forward declarations */
static void dbCaTask(void *);
static lset dbCa_lset;
#define printLinks(pcaLink) \
errlogPrintf("%s has DB CA link to %s\n",\
pcaLink->plink->value.pv_link.precord->name, pcaLink->pvname)
pcaLink->plink->precord->name, pcaLink->pvname)
static int dbca_chan_count;
/* caLink locking
*
* workListLock
* This is only used to put request into and take them out of workList.
* While this is locked no other locks are taken
* Lock ordering:
* dbScanLock -> caLink.lock -> workListLock
*
* dbScanLock
* dbCaAddLink and dbCaRemoveLink are only called by dbAccess or iocInit
* They are only called by dbAccess when it has a global lock on lock set.
* It is assumed that ALL other dbCaxxx calls are made only if dbScanLock
* is already active. These routines are intended for use by record/device
* support.
* workListLock:
* Guards access to workList.
*
* caLink.lock
* Any code that use a caLink takes this lock and releases it when done
* dbScanLock:
* All dbCa* functions operating on a single link may only be called when
* the record containing the DBLINK is locked. Including:
* dbCaGet*()
* isConnected()
* dbCaPutLink()
* scanForward()
* dbCaAddLinkCallback()
* dbCaRemoveLink()
*
* dbCaTask and the channel access callbacks NEVER access anything in the
* records except after locking caLink.lock and checking that caLink.plink
* is not null. They NEVER call dbScanLock.
* Guard the pointer plink.value.pv_link.pvt, but not the struct caLink
* which is pointed to.
*
* The above is necessary to prevent deadlocks and attempts to use a caLink
* that has been deleted.
* caLink.lock:
* Guards the caLink structure (but not the struct DBLINK)
*
* Just a few words about handling dbCaRemoveLink because this is when
* it is essential that nothing tries to use a caLink that has been freed.
* The dbCaTask only locks caLink, and must not lock the record (a violation of lock order).
*
* dbCaRemoveLink is called when links are being modified. This is only
* done with the dbScan mechanism guranteeing that nothing from
* database access trys to access the record containing the caLink.
* During link modification or IOC shutdown the pca->plink pointer (guarded by caLink.lock)
* is used as a flag to indicate that a link is no longer active.
*
* Thus the problem is to make sure that nothing from channel access
* accesses a caLink that is deleted. This is done as follows.
* References to the struct caLink are owned by the dbCaTask, and any scanOnceCallback()
* which is in progress.
*
* dbCaRemoveLink does the following:
* epicsMutexMustLock(pca->lock);
* pca->plink = 0;
* plink->value.pv_link.pvt = 0;
* epicsMutexUnlock(pca->lock);
* addAction(pca,CA_CLEAR_CHANNEL);
*
* dbCaTask issues a ca_clear_channel and then frees the caLink.
*
* If any channel access callback gets called before the ca_clear_channel
* it finds pca->plink==0 and does nothing. Once ca_clear_channel
* is called no other callback for this caLink will be called.
* The libca and scanOnceCallback callbacks take no action if pca->plink==NULL.
*
* dbCaPutLinkCallback causes an additional complication because
* when dbCaRemoveLink is called the callback may not have occured.
@@ -144,7 +140,6 @@ static void addAction(caLink *pca, short link_action)
if (++removesOutstanding >= removesOutstandingWarning) {
errlogPrintf("dbCa::addAction pausing, %d channels to clear\n",
removesOutstanding);
printLinks(pca);
}
while (removesOutstanding >= removesOutstandingWarning) {
epicsMutexUnlock(workListLock);
@@ -160,11 +155,23 @@ static void addAction(caLink *pca, short link_action)
epicsEventSignal(workListEvent);
}
static void dbCaLinkFree(caLink *pca)
static void caLinkInc(caLink *pca)
{
assert(epicsAtomicGetIntT(&pca->refcount)>0);
epicsAtomicIncrIntT(&pca->refcount);
}
static void caLinkDec(caLink *pca)
{
int cnt;
dbCaCallback callback;
void *userPvt = 0;
cnt = epicsAtomicDecrIntT(&pca->refcount);
assert(cnt>=0);
if(cnt>0)
return;
if (pca->chid) {
ca_clear_channel(pca->chid);
--dbca_chan_count;
@@ -185,52 +192,86 @@ static void dbCaLinkFree(caLink *pca)
if (callback) callback(userPvt);
}
/* Block until worker thread has processed all previously queued actions.
* Does not prevent additional actions from being queued.
*/
void dbCaSync(void)
{
epicsEventId wake;
caLink templink;
/* we only partially initialize templink.
* It has no link field and no subscription
* so the worker must handle it early
*/
memset(&templink, 0, sizeof(templink));
templink.refcount = 1;
wake = epicsEventMustCreate(epicsEventEmpty);
templink.lock = epicsMutexMustCreate();
templink.userPvt = wake;
addAction(&templink, CA_SYNC);
epicsEventMustWait(wake);
/* Worker holds workListLock when calling epicsEventMustTrigger()
* we cycle through workListLock to ensure worker call to
* epicsEventMustTrigger() returns before we destroy the event.
*/
epicsMutexMustLock(workListLock);
epicsMutexUnlock(workListLock);
assert(templink.refcount==1);
epicsMutexDestroy(templink.lock);
epicsEventDestroy(wake);
}
epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink)
{
caLink *pca = (caLink *)plink->value.pv_link.pvt;
unsigned long ret;
if (!pca) return (unsigned long)-1;
epicsMutexMustLock(pca->lock);
ret = pca->nUpdate;
epicsMutexUnlock(pca->lock);
return ret;
}
void dbCaCallbackProcess(void *userPvt)
{
struct link *plink = (struct link *)userPvt;
dbCommon *pdbCommon = plink->value.pv_link.precord;
dbScanLock(pdbCommon);
pdbCommon->rset->process(pdbCommon);
dbScanUnlock(pdbCommon);
dbLinkAsyncComplete(plink);
}
void dbCaShutdown(void)
{
if (dbCaCtl == ctlRun || dbCaCtl == ctlPause) {
dbCaCtl = ctlExit;
epicsEventSignal(workListEvent);
epicsEventMustWait(startStopEvent);
epicsEventDestroy(startStopEvent);
} else {
/* manually cleanup queue since dbCa thread isn't running
* which only happens in unit tests
*/
caLink *pca;
epicsMutexMustLock(workListLock);
while((pca=(caLink*)ellGet(&workList))!=NULL) {
if(pca->link_action&CA_CLEAR_CHANNEL) {
dbCaLinkFree(pca);
}
}
epicsMutexUnlock(workListLock);
}
enum dbCaCtl_t cur = dbCaCtl;
assert(cur == ctlRun || cur == ctlPause);
dbCaCtl = ctlExit;
epicsEventSignal(workListEvent);
epicsEventMustWait(startStopEvent);
}
void dbCaLinkInitIsolated(void)
static void dbCaLinkInitImpl(int isolate)
{
dbServiceIsolate = isolate;
dbServiceIOInit();
if (!workListLock)
workListLock = epicsMutexMustCreate();
if (!workListEvent)
workListEvent = epicsEventMustCreate(epicsEventEmpty);
dbCaCtl = ctlExit;
}
void dbCaLinkInit(void)
{
dbServiceIOInit();
dbCaLinkInitIsolated();
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
if(!startStopEvent)
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
dbCaCtl = ctlPause;
epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium,
@@ -239,6 +280,16 @@ void dbCaLinkInit(void)
epicsEventMustWait(startStopEvent);
}
void dbCaLinkInitIsolated(void)
{
dbCaLinkInitImpl(1);
}
void dbCaLinkInit(void)
{
dbCaLinkInitImpl(0);
}
void dbCaRun(void)
{
if (dbCaCtl == ctlPause) {
@@ -263,6 +314,7 @@ void dbCaAddLinkCallback(struct link *plink,
assert(!plink->value.pv_link.pvt);
pca = (caLink *)dbCalloc(1, sizeof(caLink));
pca->refcount = 1;
pca->lock = epicsMutexMustCreate();
pca->plink = plink;
pca->pvname = epicsStrDup(plink->value.pv_link.pvname);
@@ -271,13 +323,20 @@ void dbCaAddLinkCallback(struct link *plink,
pca->userPvt = userPvt;
epicsMutexMustLock(pca->lock);
plink->lset = &dbCa_lset;
plink->type = CA_LINK;
plink->value.pv_link.pvt = pca;
addAction(pca, CA_CONNECT);
epicsMutexUnlock(pca->lock);
}
void dbCaRemoveLink(struct link *plink)
long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType)
{
dbCaAddLinkCallback(plink, 0, 0, NULL);
return 0;
}
void dbCaRemoveLink(struct dbLocker *locker, struct link *plink)
{
caLink *pca = (caLink *)plink->value.pv_link.pvt;
@@ -285,13 +344,16 @@ void dbCaRemoveLink(struct link *plink)
epicsMutexMustLock(pca->lock);
pca->plink = 0;
plink->value.pv_link.pvt = 0;
plink->value.pv_link.pvlMask = 0;
plink->type = PV_LINK;
plink->lset = NULL;
/* Unlock before addAction or dbCaTask might free first */
epicsMutexUnlock(pca->lock);
addAction(pca, CA_CLEAR_CHANNEL);
}
long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
epicsEnum16 *pstat, epicsEnum16 *psevr, long *nelements)
long dbCaGetLink(struct link *plink, short dbrType, void *pdest,
long *nelements)
{
caLink *pca = (caLink *)plink->value.pv_link.pvt;
long status = 0;
@@ -344,15 +406,15 @@ long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
assert(pca->pgetNative);
status = fConvert(pca->pgetNative, pdest, 0);
} else {
long ntoget = *nelements;
unsigned long ntoget = *nelements;
struct dbAddr dbAddr;
long (*aConvert)(struct dbAddr *paddr, void *to, long nreq, long nto, long off);
aConvert = dbGetConvertRoutine[newType][dbrType];
assert(pca->pgetNative);
if (ntoget > pca->nelements)
ntoget = pca->nelements;
if (ntoget > pca->usedelements)
ntoget = pca->usedelements;
*nelements = ntoget;
memset((void *)&dbAddr, 0, sizeof(dbAddr));
@@ -363,13 +425,23 @@ long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
aConvert(&dbAddr, pdest, ntoget, ntoget, 0);
}
done:
if (pstat) *pstat = pca->stat;
if (psevr) *psevr = pca->sevr;
if (link_action) addAction(pca, link_action);
if (link_action)
addAction(pca, link_action);
if (!status)
recGblInheritSevr(plink->value.pv_link.pvlMask & pvlOptMsMode,
plink->precord, pca->stat, pca->sevr);
epicsMutexUnlock(pca->lock);
return status;
}
static long dbCaPutAsync(struct link *plink,short dbrType,
const void *pbuffer,long nRequest)
{
return dbCaPutLinkCallback(plink, dbrType, pbuffer, nRequest,
dbCaCallbackProcess, plink);
}
long dbCaPutLinkCallback(struct link *plink,short dbrType,
const void *pbuffer,long nRequest,dbCaCallback callback,void *userPvt)
{
@@ -407,6 +479,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
if (!pca->pputNative) {
pca->pputNative = dbCalloc(pca->nelements,
dbr_value_size[ca_field_type(pca->chid)]);
pca->putnelements = 0;
/* Fixed and disabled by ANJ, see comment above.
plink->value.pv_link.pvlMask |= pvlOptOutNative;
*/
@@ -416,6 +489,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
fConvert = dbFastPutConvertRoutine[dbrType][newType];
status = fConvert(pbuffer, pca->pputNative, 0);
pca->putnelements = 1;
} else {
struct dbAddr dbAddr;
long (*aConvert)(struct dbAddr *paddr, const void *from, long nreq, long nfrom, long off);
@@ -428,10 +502,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
if(nRequest>pca->nelements)
nRequest = pca->nelements;
status = aConvert(&dbAddr, pbuffer, nRequest, pca->nelements, 0);
if(nRequest<pca->nelements) {
long elemsize = dbr_value_size[ca_field_type(pca->chid)];
memset(nRequest*elemsize+(char*)pca->pputNative, 0, (pca->nelements-nRequest)*elemsize);
}
pca->putnelements = nRequest;
}
link_action |= CA_WRITE_NATIVE;
pca->gotOutNative = TRUE;
@@ -451,7 +522,13 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
return status;
}
int dbCaIsLinkConnected(const struct link *plink)
long dbCaPutLink(struct link *plink, short dbrType,
const void *pbuffer, long nRequest)
{
return dbCaPutLinkCallback(plink, dbrType, pbuffer, nRequest, 0, NULL);
}
static int isConnected(const struct link *plink)
{
caLink *pca;
@@ -461,7 +538,7 @@ int dbCaIsLinkConnected(const struct link *plink)
return pca->isConnected;
}
void dbCaScanFwdLink(struct link *plink) {
static void scanForward(struct link *plink) {
short fwdLinkValue = 1;
if (plink->value.pv_link.pvlMask & pvlOptFWD)
@@ -480,7 +557,7 @@ void dbCaScanFwdLink(struct link *plink) {
return -1; \
}
long dbCaGetNelements(const struct link *plink, long *nelements)
static long getElements(const struct link *plink, long *nelements)
{
caLink *pca;
@@ -490,7 +567,7 @@ long dbCaGetNelements(const struct link *plink, long *nelements)
return 0;
}
long dbCaGetAlarm(const struct link *plink,
static long getAlarm(const struct link *plink,
epicsEnum16 *pstat, epicsEnum16 *psevr)
{
caLink *pca;
@@ -502,7 +579,7 @@ long dbCaGetAlarm(const struct link *plink,
return 0;
}
long dbCaGetTimeStamp(const struct link *plink,
static long getTimeStamp(const struct link *plink,
epicsTimeStamp *pstamp)
{
caLink *pca;
@@ -513,7 +590,7 @@ long dbCaGetTimeStamp(const struct link *plink,
return 0;
}
int dbCaGetLinkDBFtype(const struct link *plink)
static int getDBFtype(const struct link *plink)
{
caLink *pca;
int type;
@@ -544,7 +621,7 @@ long dbCaGetAttributes(const struct link *plink,
return 0;
}
long dbCaGetControlLimits(const struct link *plink,
static long getControlLimits(const struct link *plink,
double *low, double *high)
{
caLink *pca;
@@ -560,7 +637,7 @@ long dbCaGetControlLimits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
long dbCaGetGraphicLimits(const struct link *plink,
static long getGraphicLimits(const struct link *plink,
double *low, double *high)
{
caLink *pca;
@@ -576,7 +653,7 @@ long dbCaGetGraphicLimits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
long dbCaGetAlarmLimits(const struct link *plink,
static long getAlarmLimits(const struct link *plink,
double *lolo, double *low, double *high, double *hihi)
{
caLink *pca;
@@ -594,7 +671,7 @@ long dbCaGetAlarmLimits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
long dbCaGetPrecision(const struct link *plink, short *precision)
static long getPrecision(const struct link *plink, short *precision)
{
caLink *pca;
int gotAttributes;
@@ -606,7 +683,7 @@ long dbCaGetPrecision(const struct link *plink, short *precision)
return gotAttributes ? 0 : -1;
}
long dbCaGetUnits(const struct link *plink,
static long getUnits(const struct link *plink,
char *units, int unitsSize)
{
caLink *pca;
@@ -621,6 +698,63 @@ long dbCaGetUnits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
{
caLink *pca;
long status;
pcaGetCheck
status = rtn(plink, priv);
epicsMutexUnlock(pca->lock);
return status;
}
static void scanComplete(void *raw, dbCommon *prec)
{
caLink *pca = raw;
epicsMutexMustLock(pca->lock);
if(!pca->plink) {
/* IOC shutdown or link re-targeted. Do nothing. */
} else if(pca->scanningOnce==0) {
errlogPrintf("dbCa.c complete callback w/ scanningOnce==0\n");
} else if(--pca->scanningOnce){
/* another scan is queued */
if(scanOnceCallback(prec, scanComplete, raw)) {
errlogPrintf("dbCa.c failed to re-queue scanOnce\n");
} else
caLinkInc(pca);
}
epicsMutexUnlock(pca->lock);
caLinkDec(pca);
}
/* must be called with pca->lock held */
static void scanLinkOnce(dbCommon *prec, caLink *pca) {
if(pca->scanningOnce==0) {
if(scanOnceCallback(prec, scanComplete, pca)) {
errlogPrintf("dbCa.c failed to queue scanOnce\n");
} else
caLinkInc(pca);
}
if(pca->scanningOnce<5)
pca->scanningOnce++;
/* else too many scans queued */
}
static lset dbCa_lset = {
0, 1, /* not Constant, Volatile */
NULL, dbCaRemoveLink,
NULL, NULL, NULL,
isConnected,
getDBFtype, getElements,
dbCaGetLink,
getControlLimits, getGraphicLimits, getAlarmLimits,
getPrecision, getUnits,
getAlarm, getTimeStamp,
dbCaPutLink, dbCaPutAsync,
scanForward, doLocked
};
static void connectionCallback(struct connection_handler_args arg)
{
caLink *pca;
@@ -635,13 +769,13 @@ static void connectionCallback(struct connection_handler_args arg)
pca->isConnected = (ca_state(arg.chid) == cs_conn);
if (!pca->isConnected) {
struct pv_link *ppv_link = &plink->value.pv_link;
dbCommon *precord = ppv_link->precord;
dbCommon *precord = plink->precord;
pca->nDisconnect++;
if (precord &&
((ppv_link->pvlMask & pvlOptCP) ||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0)))
scanOnce(precord);
scanLinkOnce(precord, pca);
goto done;
}
pca->hasReadAccess = ca_read_access(arg.chid);
@@ -671,6 +805,7 @@ static void connectionCallback(struct connection_handler_args arg)
}
pca->gotFirstConnection = TRUE;
pca->nelements = ca_element_count(arg.chid);
pca->usedelements = 0;
pca->dbrType = ca_field_type(arg.chid);
if ((plink->value.pv_link.pvlMask & pvlOptInpNative) && !pca->pgetNative) {
link_action |= CA_MONITOR_NATIVE;
@@ -707,9 +842,10 @@ static void eventCallback(struct event_handler_args arg)
epicsMutexMustLock(pca->lock);
plink = pca->plink;
if (!plink) goto done;
pca->nUpdate++;
monitor = pca->monitor;
userPvt = pca->userPvt;
precord = plink->value.pv_link.precord;
precord = plink->precord;
if (arg.status != ECA_NORMAL) {
if (precord) {
if (arg.status != ECA_NORDACCESS &&
@@ -723,6 +859,7 @@ static void eventCallback(struct event_handler_args arg)
goto done;
}
assert(arg.dbr);
assert(arg.count<=pca->nelements);
size = arg.count * dbr_value_size[arg.type];
if (arg.type == DBR_TIME_STRING &&
ca_field_type(pca->chid) == DBR_ENUM) {
@@ -739,10 +876,12 @@ static void eventCallback(struct event_handler_args arg)
case DBR_TIME_DOUBLE:
assert(pca->pgetNative);
memcpy(pca->pgetNative, dbr_value_ptr(arg.dbr, arg.type), size);
pca->usedelements = arg.count;
pca->gotInNative = TRUE;
break;
default:
errMessage(-1, "dbCa: eventCallback Logic Error\n");
errlogPrintf("dbCa: eventCallback Logic Error. dbr=%ld dbf=%d\n",
arg.type, ca_field_type(pca->chid));
break;
}
pdbr_time_double = (struct dbr_time_double *)arg.dbr;
@@ -754,7 +893,7 @@ static void eventCallback(struct event_handler_args arg)
if ((ppv_link->pvlMask & pvlOptCP) ||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0))
scanOnce(precord);
scanLinkOnce(precord, pca);
}
done:
epicsMutexUnlock(pca->lock);
@@ -823,11 +962,11 @@ static void accessRightsCallback(struct access_rights_handler_args arg)
pca->hasWriteAccess = ca_write_access(arg.chid);
if (pca->hasReadAccess && pca->hasWriteAccess) goto done;
ppv_link = &plink->value.pv_link;
precord = ppv_link->precord;
precord = plink->precord;
if (precord &&
((ppv_link->pvlMask & pvlOptCP) ||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0)))
scanOnce(precord);
scanLinkOnce(precord, pca);
done:
epicsMutexUnlock(pca->lock);
}
@@ -854,7 +993,7 @@ static void getAttribEventCallback(struct event_handler_args arg)
getAttributes = pca->getAttributes;
getAttributesPvt = pca->getAttributesPvt;
if (arg.status != ECA_NORMAL) {
dbCommon *precord = plink->value.pv_link.precord;
dbCommon *precord = plink->precord;
if (precord) {
errlogPrintf("dbCa: getAttribEventCallback record %s error %s\n",
precord->name, ca_message(arg.status));
@@ -910,11 +1049,15 @@ static void dbCaTask(void *arg)
break; /* workList is empty */
}
link_action = pca->link_action;
if (link_action&CA_SYNC)
epicsEventMustTrigger((epicsEventId)pca->userPvt); /* dbCaSync() requires workListLock to be held here */
pca->link_action = 0;
if (link_action & CA_CLEAR_CHANNEL) --removesOutstanding;
epicsMutexUnlock(workListLock); /* Give back immediately */
if (link_action&CA_SYNC)
continue;
if (link_action & CA_CLEAR_CHANNEL) { /* This must be first */
dbCaLinkFree(pca);
caLinkDec(pca);
/* No alarm is raised. Since link is changing so what? */
continue; /* No other link_action makes sense */
}
@@ -943,11 +1086,11 @@ static void dbCaTask(void *arg)
assert(pca->pputNative);
if (pca->putType == CA_PUT) {
status = ca_array_put(
pca->dbrType, pca->nelements,
pca->dbrType, pca->putnelements,
pca->chid, pca->pputNative);
} else if (pca->putType==CA_PUT_CALLBACK) {
status = ca_array_put_callback(
pca->dbrType, pca->nelements,
pca->dbrType, pca->putnelements,
pca->chid, pca->pputNative,
putComplete, pca);
} else {
@@ -997,15 +1140,15 @@ static void dbCaTask(void *arg)
}
}
if (link_action & CA_MONITOR_NATIVE) {
size_t element_size;
element_size = dbr_value_size[ca_field_type(pca->chid)];
epicsMutexMustLock(pca->lock);
pca->pgetNative = dbCalloc(pca->nelements, element_size);
pca->elementSize = dbr_value_size[ca_field_type(pca->chid)];
pca->pgetNative = dbCalloc(pca->nelements, pca->elementSize);
epicsMutexUnlock(pca->lock);
status = ca_add_array_event(
ca_field_type(pca->chid)+DBR_TIME_STRING,
ca_element_count(pca->chid),
dbf_type_to_DBR_TIME(ca_field_type(pca->chid)),
0, /* dynamic size */
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",

View File

@@ -1,20 +1,17 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2015 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbCa.h */
/* dbCa.h */
#ifndef INCdbCah
#define INCdbCah
#include "shareLib.h"
#include "epicsTime.h"
#include "link.h"
#include "dbLink.h"
#ifdef __cplusplus
extern "C" {
@@ -29,48 +26,60 @@ epicsShareFunc void dbCaRun(void);
epicsShareFunc void dbCaPause(void);
epicsShareFunc void dbCaShutdown(void);
struct dbLocker;
epicsShareFunc void dbCaAddLinkCallback(struct link *plink,
dbCaCallback connect, dbCaCallback monitor, void *userPvt);
#define dbCaAddLink(plink) dbCaAddLinkCallback((plink), 0, 0, 0)
epicsShareFunc void dbCaRemoveLink(struct link *plink);
epicsShareFunc long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType);
epicsShareFunc void dbCaRemoveLink(struct dbLocker *locker, struct link *plink);
epicsShareFunc long dbCaGetLink(struct link *plink,
short dbrType, void *pbuffer, epicsEnum16 *pstat, epicsEnum16 *psevr,
long *nRequest);
short dbrType, void *pbuffer, long *nRequest);
epicsShareFunc long dbCaGetAttributes(const struct link *plink,
dbCaCallback callback, void *userPvt);
epicsShareFunc long dbCaPutLinkCallback(struct link *plink,
short dbrType, const void *pbuffer,long nRequest,
dbCaCallback callback, void *userPvt);
#define dbCaPutLink(plink, dbrType, pbuffer, nRequest) \
dbCaPutLinkCallback((plink), (dbrType), (pbuffer), (nRequest), 0, 0)
epicsShareFunc int dbCaIsLinkConnected(const struct link *plink);
epicsShareFunc void dbCaScanFwdLink(struct link *plink);
/* The following are available after the link is connected*/
epicsShareFunc long dbCaGetNelements(const struct link *plink,
long *nelements);
#define dbCaGetSevr(plink, severity) \
dbCaGetAlarm((plink), NULL, (severity))
epicsShareFunc long dbCaGetAlarm(const struct link *plink,
epicsEnum16 *status, epicsEnum16 *severity);
epicsShareFunc long dbCaGetTimeStamp(const struct link *plink,
epicsTimeStamp *pstamp);
epicsShareFunc int dbCaGetLinkDBFtype(const struct link *plink);
/*The following are available after attribute request is complete*/
epicsShareFunc long dbCaGetAttributes(const struct link *plink,
dbCaCallback callback, void *userPvt);
epicsShareFunc long dbCaGetControlLimits(const struct link *plink,
double *low, double *high);
epicsShareFunc long dbCaGetGraphicLimits(const struct link *plink,
double *low, double *high);
epicsShareFunc long dbCaGetAlarmLimits(const struct link *plink,
double *lolo, double *low, double *high, double *hihi);
epicsShareFunc long dbCaGetPrecision(const struct link *plink,
short *precision);
epicsShareFunc long dbCaGetUnits(const struct link *plink,
char *units, int unitsSize);
epicsShareFunc long dbCaPutLink(struct link *plink,short dbrType,
const void *pbuffer,long nRequest);
extern struct ca_client_context * dbCaClientContext;
#ifdef EPICS_DBCA_PRIVATE_API
epicsShareFunc void dbCaSync(void);
epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink);
#endif
/* These macros are for backwards compatibility */
#define dbCaIsLinkConnected(link) \
dbIsLinkConnected(link)
#define dbCaGetLinkDBFtype(link) \
dbGetLinkDBFtype(link)
#define dbCaGetNelements(link, nelements) \
dbGetNelements(link, nelements)
#define dbCaGetSevr(link, sevr) \
dbGetAlarm(link, NULL, sevr)
#define dbCaGetAlarm(link, stat, sevr) \
dbGetAlarm(link, stat, sevr)
#define dbCaGetTimeStamp(link, pstamp) \
dbGetTimeStamp(link, pstamp)
#define dbCaGetControlLimits(link, low, high) \
dbGetControlLimits(link, low, high)
#define dbCaGetGraphicLimits(link, low, high) \
dbGetGraphicLimits(link, low, high)
#define dbCaGetAlarmLimits(link, lolo, low, high, hihi) \
dbGetAlarmLimits(link, lolo, low, high, hihi)
#define dbCaGetPrecision(link, prec) \
dbGetPrecision(link, prec)
#define dbCaGetUnits(link, units, unitSize) \
dbGetUnits(link, units, unitSize)
#define dbCaScanFwdLink(link) \
dbScanFwdLink(link)
#ifdef __cplusplus
}
#endif

View File

@@ -6,14 +6,11 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbCaPvt.h */
/****************************************************************
*
* Current Author: Bob Dalesio
* Contributing Author: Marty Kraimer
* Date: 08APR96
*
****************************************************************/
/* dbCaPvt.h
*
* Original Authors: Bob Dalesio, Marty Kraimer
*
*/
#ifndef INC_dbCaPvt_H
#define INC_dbCaPvt_H
@@ -32,61 +29,68 @@
#define CA_MONITOR_NATIVE 0x10
#define CA_MONITOR_STRING 0x20
#define CA_GET_ATTRIBUTES 0x40
#define CA_SYNC 0x1000
/* write type */
#define CA_PUT 0x1
#define CA_PUT_CALLBACK 0x2
typedef struct caLink
{
ELLNODE node;
epicsMutexId lock;
struct link *plink;
char *pvname;
chid chid;
short link_action;
/* The following have new values after each data event*/
epicsEnum16 sevr;
epicsEnum16 stat;
epicsTimeStamp timeStamp;
/* The following have values after connection*/
short dbrType;
long nelements;
char hasReadAccess;
char hasWriteAccess;
char isConnected;
char gotFirstConnection;
/* The following are for dbCaAddLinkCallback */
dbCaCallback connect;
dbCaCallback monitor;
void *userPvt;
/* The following are for write request */
short putType;
dbCaCallback putCallback;
void *putUserPvt;
/* The following are for access to additional attributes*/
char gotAttributes;
dbCaCallback getAttributes;
void *getAttributesPvt;
/* The following have values after getAttribEventCallback*/
double controlLimits[2];
double displayLimits[2];
double alarmLimits[4];
short precision;
char units[MAX_UNITS_SIZE]; /* units of value */
/* The following are for handling data*/
void *pgetNative;
char *pgetString;
void *pputNative;
char *pputString;
char gotInNative;
char gotInString;
char gotOutNative;
char gotOutString;
char newOutNative;
char newOutString;
/* The following are for dbcar*/
unsigned long nDisconnect;
unsigned long nNoWrite; /*only modified by dbCaPutLink*/
ELLNODE node;
int refcount;
epicsMutexId lock;
struct link *plink;
char *pvname;
chid chid;
short link_action;
/* The following have new values after each data event*/
epicsEnum16 sevr;
epicsEnum16 stat;
epicsTimeStamp timeStamp;
/* The following have values after connection*/
short dbrType;
size_t elementSize; /* size of one element in pgetNative */
unsigned long nelements; /* PVs max array size */
unsigned long usedelements; /* currently used in pgetNative */
unsigned long putnelements; /* currently used in pputNative */
char hasReadAccess;
char hasWriteAccess;
char isConnected;
char gotFirstConnection;
/* The following are for dbCaAddLinkCallback */
dbCaCallback connect;
dbCaCallback monitor;
void *userPvt;
/* The following are for write request */
short putType;
dbCaCallback putCallback;
void *putUserPvt;
/* The following are for access to additional attributes*/
char gotAttributes;
dbCaCallback getAttributes;
void *getAttributesPvt;
/* The following have values after getAttribEventCallback*/
double controlLimits[2];
double displayLimits[2];
double alarmLimits[4];
short precision;
char units[MAX_UNITS_SIZE]; /* units of value */
/* The following are for handling data*/
void *pgetNative;
char *pgetString;
void *pputNative;
char *pputString;
char gotInNative;
char gotInString;
char gotOutNative;
char gotOutString;
char newOutNative;
char newOutString;
unsigned char scanningOnce;
/* The following are for dbcar*/
unsigned long nDisconnect;
unsigned long nNoWrite; /*only modified by dbCaPutLink*/
unsigned long nUpdate;
}caLink;
#endif /* INC_dbCaPvt_H */

View File

@@ -87,10 +87,10 @@ long dbcar(char *precordname, int level)
!dbIsAlias(pdbentry)) {
pdbRecordType = pdbentry->precordType;
precord = (dbCommon *)pdbentry->precnode->precord;
dbScanLock(precord);
for (j=0; j<pdbRecordType->no_links; j++) {
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[j]];
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
dbLockSetGblLock();
if (plink->type == CA_LINK) {
ncalinks++;
pca = (caLink *)plink->value.pv_link.pvt;
@@ -130,13 +130,13 @@ long dbcar(char *precordname, int level)
precord->name,
pdbFldDes->name,
plink->value.pv_link.pvname,
pca->nDisconnect,
pca->nNoWrite);
pca ? pca->nDisconnect : 0,
pca ? pca->nNoWrite : 0);
}
}
}
dbLockSetGblUnlock();
}
dbScanUnlock(precord);
if (precordname) goto done;
}
status = dbNextRecord(pdbentry);
@@ -189,10 +189,8 @@ void dbcaStats(int *pchans, int *pdiscon)
dbFldDes *pdbFldDes = pdbRecordType->papFldDes[i];
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
if (plink->type == CA_LINK) {
caLink *pca = (caLink *)plink->value.pv_link.pvt;
ncalinks++;
if (pca && pca->chid && ca_state(pca->chid) == cs_conn) {
if (dbCaIsLinkConnected(plink)) {
nconnected++;
}
}

View File

@@ -19,7 +19,6 @@
#include "cantProceed.h"
#include "epicsAssert.h"
#include "epicsExit.h"
#include "epicsString.h"
#include "errlog.h"
#include "freeList.h"
@@ -455,6 +454,8 @@ static short mapDBFToDBR[DBF_NTYPES] =
/* DBF_USHORT => */DBR_USHORT,
/* DBF_LONG => */DBR_LONG,
/* DBF_ULONG => */DBR_ULONG,
/* DBF_INT64 => */DBR_INT64,
/* DBF_UINT64 => */DBR_UINT64,
/* DBF_FLOAT => */DBR_FLOAT,
/* DBF_DOUBLE => */DBR_DOUBLE,
/* DBF_ENUM, => */DBR_ENUM,
@@ -510,7 +511,7 @@ dbChannel * dbChannelCreate(const char *name)
paddr->dbr_field_type = mapDBFToDBR[dbfType];
if (paddr->special == SPC_DBADDR) {
struct rset *prset = dbGetRset(paddr);
rset *prset = dbGetRset(paddr);
/* Let record type modify paddr */
if (prset && prset->cvt_dbaddr) {
@@ -532,7 +533,7 @@ dbChannel * dbChannelCreate(const char *name)
paddr->dbr_field_type = DBR_CHAR;
} else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
/* Clients see a char array, but keep original dbfType */
paddr->no_elements = PVNAME_STRINGSZ + 12;
paddr->no_elements = PVLINK_STRINGSZ;
paddr->field_size = 1;
paddr->dbr_field_type = DBR_CHAR;
} else {

View File

@@ -26,7 +26,6 @@
#endif
#include "compilerDependencies.h"
#include "epicsMemory.h"
#ifdef dbChannelIOh_restore_epicsExportSharedSymbols
# define epicsExportSharedSymbols

118
src/ioc/db/dbChannelNOOP.h Normal file
View File

@@ -0,0 +1,118 @@
#ifndef DBCHANNELNOOP_H
#define DBCHANNELNOOP_H
#include <string.h>
#include <string>
#include "cacIO.h"
#include "caerr.h"
/** @brief A channel which never connects
*
* Used when dbCa is placed in isolated mode for unittests
*/
class dbChannelNOOP : public cacChannel
{
std::string myname;
public:
dbChannelNOOP(const char *name, cacChannelNotify &notify)
:cacChannel(notify)
,myname(name)
{}
virtual void destroy (
CallbackGuard & /*callbackGuard*/,
epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ )
{
delete this; // goodbye cruel world
}
virtual unsigned getName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLen ) const throw ()
{
const char* name = myname.c_str();
if(bufLen>myname.size()+1) {
bufLen=myname.size()+1;
}
memcpy(pBuf, name, bufLen);
pBuf[--bufLen] = '\0';
return bufLen;
}
// !! deprecated, avoid use !!
virtual const char * pName (
epicsGuard < epicsMutex > & guard ) const throw ()
{return myname.c_str();}
virtual void show (
epicsGuard < epicsMutex > &,
unsigned level ) const
{}
virtual void initiateConnect (
epicsGuard < epicsMutex > & )
{}
virtual unsigned requestMessageBytesPending (
epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ )
{return 0;}
virtual void flush (
epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ )
{}
virtual ioStatus read (
epicsGuard < epicsMutex > &mut,
unsigned type, arrayElementCount count,
cacReadNotify &notify, ioid * = 0 )
{
notify.exception(mut, ECA_NORDACCESS, "dbChannelNOOP", type, count);
return iosSynch;
}
virtual void write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
const void *pValue )
{}
virtual ioStatus write (
epicsGuard < epicsMutex > &mut,
unsigned type, arrayElementCount count,
const void */*pValue*/, cacWriteNotify & notify, ioid * = 0 )
{
notify.exception(mut, ECA_NOWTACCESS, "dbChannelNOOP", type, count);
return iosSynch;
}
virtual void subscribe (
epicsGuard < epicsMutex > &mut, unsigned type,
arrayElementCount count, unsigned /*mask*/, cacStateNotify & notify,
ioid * = 0 )
{
// should never subscribe
notify.exception(mut, ECA_BADMASK, "dbChannelNOOP", type, count);
}
virtual void ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & )
{}
virtual void ioShow (
epicsGuard < epicsMutex > &,
const ioid &, unsigned level ) const
{}
virtual short nativeType (
epicsGuard < epicsMutex > & ) const
{return 0;} // DBR_STRING
virtual arrayElementCount nativeElementCount (
epicsGuard < epicsMutex > & ) const
{return 1;}
};
#endif // DBCHANNELNOOP_H

View File

@@ -92,6 +92,12 @@
interest(4)
extra("ELLLIST mlis")
}
field(BKLNK,DBF_NOACCESS) {
prompt("Backwards link tracking")
special(SPC_NOMOD)
interest(4)
extra("ELLLIST bklnk")
}
field(DISP,DBF_UCHAR) {
prompt("Disable putField")
}
@@ -191,7 +197,7 @@
prompt("Address of RSET")
special(SPC_NOMOD)
interest(4)
extra("struct rset *rset")
extra("struct typed_rset *rset")
}
field(DSET,DBF_NOACCESS) {
prompt("DSET address")

14
src/ioc/db/dbCommonPvt.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef DBCOMMONPVT_H
#define DBCOMMONPVT_H
#include "dbCommon.h"
/** Base internal additional information for every record
*/
typedef struct dbCommonPvt {
struct dbRecordNode *recnode;
struct dbCommon common;
} dbCommonPvt;
#endif // DBCOMMONPVT_H

126
src/ioc/db/dbConstLink.c Normal file
View File

@@ -0,0 +1,126 @@
/*************************************************************************\
* Copyright (c) 2010 UChicago Argonne LLC, 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.
\*************************************************************************/
/* dbConstLink.c
*
* Original Authors: Bob Dalesio, Marty Kraimer
* Current Author: Andrew Johnson
*/
#include <stdio.h>
#include <string.h>
#include "dbDefs.h"
#define epicsExportSharedSymbols
#include "dbAccessDefs.h"
#include "dbAddr.h"
#include "dbCommon.h"
#include "dbConstLink.h"
#include "dbConvertFast.h"
#include "dbConvertJSON.h"
#include "dbFldTypes.h"
#include "dbLink.h"
#include "link.h"
/***************************** Constant Links *****************************/
/* Forward definition */
static lset dbConst_lset;
void dbConstInitLink(struct link *plink)
{
plink->lset = &dbConst_lset;
}
void dbConstAddLink(struct link *plink)
{
plink->lset = &dbConst_lset;
}
/**************************** Member functions ****************************/
static long dbConstLoadScalar(struct link *plink, short dbrType, void *pbuffer)
{
const char *pstr = plink->value.constantStr;
size_t len;
if (!pstr)
return S_db_badField;
len = strlen(pstr);
/* Choice values must be numeric */
if (dbrType == DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE)
dbrType = DBF_USHORT;
if (*pstr == '[' && pstr[len-1] == ']') {
/* Convert from JSON array */
long nReq = 1;
return dbPutConvertJSON(pstr, dbrType, pbuffer, &nReq);
}
return dbFastPutConvertRoutine[DBR_STRING][dbrType]
(pstr, pbuffer, NULL);
}
static long dbConstLoadLS(struct link *plink, char *pbuffer, epicsUInt32 size,
epicsUInt32 *plen)
{
const char *pstr = plink->value.constantStr;
if (!pstr)
return S_db_badField;
return dbLSConvertJSON(pstr, pbuffer, size, plen);
}
static long dbConstLoadArray(struct link *plink, short dbrType, void *pbuffer,
long *pnReq)
{
const char *pstr = plink->value.constantStr;
if (!pstr)
return S_db_badField;
/* Choice values must be numeric */
if (dbrType == DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE)
dbrType = DBF_USHORT;
return dbPutConvertJSON(pstr, dbrType, pbuffer, pnReq);
}
static long dbConstGetNelements(const struct link *plink, long *nelements)
{
*nelements = 0;
return 0;
}
static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer,
long *pnRequest)
{
if (pnRequest)
*pnRequest = 0;
return 0;
}
static lset dbConst_lset = {
1, 0, /* Constant, not Volatile */
NULL, NULL,
dbConstLoadScalar,
dbConstLoadLS,
dbConstLoadArray,
NULL,
NULL, dbConstGetNelements,
dbConstGetValue,
NULL, NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL
};

34
src/ioc/db/dbConstLink.h Normal file
View File

@@ -0,0 +1,34 @@
/*************************************************************************\
* Copyright (c) 2016 UChicago Argonne LLC, 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.
\*************************************************************************/
/* dbConstLink.h
*
* Created on: April 3rd, 2016
* Author: Andrew Johnson
*/
#ifndef INC_dbConstLink_H
#define INC_dbConstLink_H
#include "shareLib.h"
#ifdef __cplusplus
extern "C" {
#endif
struct link;
epicsShareFunc void dbConstInitLink(struct link *plink);
epicsShareFunc void dbConstAddLink(struct link *plink);
#ifdef __cplusplus
}
#endif
#endif /* INC_dbConstLink_H */

View File

@@ -29,6 +29,7 @@
#include "dbCAC.h"
#include "dbChannel.h"
#include "dbChannelIO.h"
#include "dbChannelNOOP.h"
#include "dbPutNotifyBlocker.h"
class dbService : public cacService {
@@ -51,9 +52,16 @@ cacContext & dbService::contextCreate (
mutualExclusion, notify );
}
extern "C" int dbServiceIsolate;
int dbServiceIsolate = 0;
extern "C" void dbServiceIOInit ()
{
caInstallDefaultService ( dbs );
static int init=0;
if(!init) {
caInstallDefaultService ( dbs );
init=1;
}
}
dbBaseIO::dbBaseIO () {}
@@ -62,7 +70,8 @@ dbContext::dbContext ( epicsMutex & cbMutexIn,
epicsMutex & mutexIn, cacContextNotify & notifyIn ) :
readNotifyCache ( mutexIn ), ctx ( 0 ),
stateNotifyCacheSize ( 0 ), mutex ( mutexIn ), cbMutex ( cbMutexIn ),
notify ( notifyIn ), pNetContext ( 0 ), pStateNotifyCache ( 0 )
notify ( notifyIn ), pNetContext ( 0 ), pStateNotifyCache ( 0 ),
isolated(dbServiceIsolate)
{
}
@@ -82,7 +91,10 @@ cacChannel & dbContext::createChannel (
dbChannel *dbch = dbChannel_create ( pName );
if ( ! dbch ) {
if ( ! this->pNetContext.get() ) {
if ( isolated ) {
return *new dbChannelNOOP(pName, notifyIn);
} else if ( ! this->pNetContext.get() ) {
this->pNetContext.reset (
& this->notify.createNetworkContext (
this->mutex, this->cbMutex ) );
@@ -132,7 +144,8 @@ void dbContext::callStateNotify ( struct dbChannel * dbch,
const struct db_field_log * pfl,
cacStateNotify & notifyIn )
{
unsigned long size = dbr_size_n ( type, count );
long realcount = (count==0)?dbChannelElements(dbch):count;
unsigned long size = dbr_size_n ( type, realcount );
if ( type > INT_MAX ) {
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -159,8 +172,13 @@ void dbContext::callStateNotify ( struct dbChannel * dbch,
this->stateNotifyCacheSize = size;
}
void *pvfl = (void *) pfl;
int status = dbChannel_get ( dbch, static_cast <int> ( type ),
this->pStateNotifyCache, static_cast <int> ( count ), pvfl );
int status;
if(count==0) /* fetch actual number of elements (dynamic array) */
status = dbChannel_get_count( dbch, static_cast <int> ( type ),
this->pStateNotifyCache, &realcount, pvfl );
else /* fetch requested number of elements, truncated or zero padded */
status = dbChannel_get( dbch, static_cast <int> ( type ),
this->pStateNotifyCache, realcount, pvfl );
if ( status ) {
epicsGuard < epicsMutex > guard ( this->mutex );
notifyIn.exception ( guard, ECA_GETFAIL,
@@ -168,7 +186,7 @@ void dbContext::callStateNotify ( struct dbChannel * dbch,
}
else {
epicsGuard < epicsMutex > guard ( this->mutex );
notifyIn.current ( guard, type, count, this->pStateNotifyCache );
notifyIn.current ( guard, type, realcount, this->pStateNotifyCache );
}
}

View File

@@ -60,27 +60,32 @@ void dbContextReadNotifyCache::callReadNotify (
return;
}
if ( dbChannelElements(dbch) < 0 ) {
const long maxcount = dbChannelElements(dbch);
if ( maxcount < 0 ) {
notify.exception ( guard, ECA_BADCOUNT,
"database has negetive element count",
type, count);
return;
}
if ( count > static_cast < unsigned long > ( dbChannelElements(dbch) ) ) {
} else if ( count > (unsigned long)maxcount ) {
notify.exception ( guard, ECA_BADCOUNT,
"element count out of range (high side)",
type, count);
return;
}
unsigned long size = dbr_size_n ( type, count );
long realcount = (count==0)?maxcount:count;
unsigned long size = dbr_size_n ( type, realcount );
privateAutoDestroyPtr ptr ( _allocator, size );
int status;
{
epicsGuardRelease < epicsMutex > unguard ( guard );
status = dbChannel_get ( dbch, static_cast <int> ( type ),
ptr.get (), static_cast <long> ( count ), 0 );
if ( count==0 )
status = dbChannel_get_count ( dbch, (int)type, ptr.get(), &realcount, 0);
else
status = dbChannel_get ( dbch, (int)type, ptr.get (), realcount, 0 );
}
if ( status ) {
notify.exception ( guard, ECA_GETFAIL,
@@ -89,7 +94,7 @@ void dbContextReadNotifyCache::callReadNotify (
}
else {
notify.completion (
guard, type, count, ptr.get () );
guard, type, realcount, ptr.get () );
}
}

File diff suppressed because it is too large Load Diff

257
src/ioc/db/dbConvertJSON.c Normal file
View File

@@ -0,0 +1,257 @@
/*************************************************************************\
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbConvertJSON.c */
#include <string.h>
#include <stdio.h>
#include "dbDefs.h"
#include "errlog.h"
#include "yajl_alloc.h"
#include "yajl_parse.h"
#define epicsExportSharedSymbols
#include "dbAccessDefs.h"
#include "dbConvertFast.h"
#include "dbConvertJSON.h"
typedef long (*FASTCONVERT)();
typedef struct parseContext {
int depth;
short dbrType;
short dbrSize;
char *pdest;
int elems;
} parseContext;
static int dbcj_null(void *ctx) {
return 0; /* Illegal */
}
static int dbcj_boolean(void *ctx, int val) {
return 0; /* Illegal */
}
static int dbcj_integer(void *ctx, long num) {
parseContext *parser = (parseContext *) ctx;
epicsInt32 val32 = num;
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_LONG][parser->dbrType];
if (parser->elems > 0) {
conv(&val32, parser->pdest, NULL);
parser->pdest += parser->dbrSize;
parser->elems--;
}
return 1;
}
static int dblsj_integer(void *ctx, long num) {
return 0; /* Illegal */
}
static int dbcj_double(void *ctx, double num) {
parseContext *parser = (parseContext *) ctx;
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_DOUBLE][parser->dbrType];
if (parser->elems > 0) {
conv(&num, parser->pdest, NULL);
parser->pdest += parser->dbrSize;
parser->elems--;
}
return 1;
}
static int dblsj_double(void *ctx, double num) {
return 0; /* Illegal */
}
static int dbcj_string(void *ctx, const unsigned char *val, unsigned int len) {
parseContext *parser = (parseContext *) ctx;
char *pdest = parser->pdest;
/* Not attempting to handle char-array fields here, they need more
* metadata about the field than we have available at the moment.
*/
if (parser->dbrType != DBF_STRING) {
errlogPrintf("dbConvertJSON: String provided, numeric value(s) expected\n");
return 0; /* Illegal */
}
if (parser->elems > 0) {
if (len > parser->dbrSize - 1)
len = parser->dbrSize - 1;
strncpy(pdest, (const char *) val, len);
pdest[len] = 0;
parser->pdest += parser->dbrSize;
parser->elems--;
}
return 1;
}
static int dblsj_string(void *ctx, const unsigned char *val, unsigned int len) {
parseContext *parser = (parseContext *) ctx;
char *pdest = parser->pdest;
if (parser->dbrType != DBF_STRING) {
errlogPrintf("dbConvertJSON: dblsj_string dbrType error\n");
return 0; /* Illegal */
}
if (parser->elems > 0) {
if (len > parser->dbrSize - 1)
len = parser->dbrSize - 1;
strncpy(pdest, (const char *) val, len);
pdest[len] = 0;
parser->pdest = pdest + len;
parser->elems = 0;
}
return 1;
}
static int dbcj_start_map(void *ctx) {
errlogPrintf("dbConvertJSON: Map type not supported\n");
return 0; /* Illegal */
}
static int dbcj_map_key(void *ctx, const unsigned char *key, unsigned int len) {
return 0; /* Illegal */
}
static int dbcj_end_map(void *ctx) {
return 0; /* Illegal */
}
static int dbcj_start_array(void *ctx) {
parseContext *parser = (parseContext *) ctx;
if (++parser->depth > 1)
errlogPrintf("dbConvertJSON: Embedded arrays not supported\n");
return (parser->depth == 1);
}
static int dbcj_end_array(void *ctx) {
parseContext *parser = (parseContext *) ctx;
parser->depth--;
return (parser->depth == 0);
}
static yajl_callbacks dbcj_callbacks = {
dbcj_null, dbcj_boolean, dbcj_integer, dbcj_double, NULL, dbcj_string,
dbcj_start_map, dbcj_map_key, dbcj_end_map,
dbcj_start_array, dbcj_end_array
};
static const yajl_parser_config dbcj_config =
{ 0, 0 }; /* allowComments = NO, checkUTF8 = NO */
long dbPutConvertJSON(const char *json, short dbrType,
void *pdest, long *pnRequest)
{
parseContext context, *parser = &context;
yajl_alloc_funcs dbcj_alloc;
yajl_handle yh;
yajl_status ys;
size_t jlen = strlen(json);
long status;
parser->depth = 0;
parser->dbrType = dbrType;
parser->dbrSize = dbValueSize(dbrType);
parser->pdest = pdest;
parser->elems = *pnRequest;
yajl_set_default_alloc_funcs(&dbcj_alloc);
yh = yajl_alloc(&dbcj_callbacks, &dbcj_config, &dbcj_alloc, parser);
if (!yh)
return S_db_noMemory;
ys = yajl_parse(yh, (const unsigned char *) json, (unsigned int) jlen);
if (ys == yajl_status_insufficient_data)
ys = yajl_parse_complete(yh);
switch (ys) {
case yajl_status_ok:
*pnRequest -= parser->elems;
status = 0;
break;
case yajl_status_error: {
unsigned char *err = yajl_get_error(yh, 1,
(const unsigned char *) json, (unsigned int) jlen);
fprintf(stderr, "dbConvertJSON: %s\n", err);
yajl_free_error(yh, err);
}
/* fall through */
default:
status = S_db_badField;
}
yajl_free(yh);
return status;
}
static yajl_callbacks dblsj_callbacks = {
dbcj_null, dbcj_boolean, dblsj_integer, dblsj_double, NULL, dblsj_string,
dbcj_start_map, dbcj_map_key, dbcj_end_map,
dbcj_start_array, dbcj_end_array
};
long dbLSConvertJSON(const char *json, char *pdest, epicsUInt32 size,
epicsUInt32 *plen)
{
parseContext context, *parser = &context;
yajl_alloc_funcs dbcj_alloc;
yajl_handle yh;
yajl_status ys;
size_t jlen = strlen(json);
long status;
if (!size) {
*plen = 0;
return 0;
}
parser->depth = 0;
parser->dbrType = DBF_STRING;
parser->dbrSize = size;
parser->pdest = pdest;
parser->elems = 1;
yajl_set_default_alloc_funcs(&dbcj_alloc);
yh = yajl_alloc(&dblsj_callbacks, &dbcj_config, &dbcj_alloc, parser);
if (!yh)
return S_db_noMemory;
ys = yajl_parse(yh, (const unsigned char *) json, (unsigned int) jlen);
if (ys == yajl_status_insufficient_data)
ys = yajl_parse_complete(yh);
switch (ys) {
case yajl_status_ok:
*plen = (char *) parser->pdest - pdest + 1;
status = 0;
break;
case yajl_status_error: {
unsigned char *err = yajl_get_error(yh, 1,
(const unsigned char *) json, (unsigned int) jlen);
fprintf(stderr, "dbLoadLS_JSON: %s\n", err);
yajl_free_error(yh, err);
}
/* fall through */
default:
status = S_db_badField;
}
yajl_free(yh);
return status;
}

View File

@@ -0,0 +1,28 @@
/*************************************************************************\
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbConvertJSON.h */
#ifndef INC_dbConvertJSON_H
#define INC_dbConvertJSON_H
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
/* This name should probably be changed to inclue "array" */
epicsShareFunc long dbPutConvertJSON(const char *json, short dbrType,
void *pdest, long *psize);
epicsShareFunc long dbLSConvertJSON(const char *json, char *pdest,
epicsUInt32 size, epicsUInt32 *plen);
#ifdef __cplusplus
}
#endif
#endif /* INC_dbConvertJSON_H */

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